simple-graph-query 2.7.2 → 2.8.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.
@@ -48590,7 +48590,7 @@ function bitwidthWraparound(value, bitwidth) {
48590
48590
  // this is a list of forge builtin functions we currently support; add to this
48591
48591
  // list as we support more
48592
48592
  const SUPPORTED_BINARY_BUILTINS = ["add", "subtract", "multiply", "divide", "remainder"];
48593
- const SUPPORTED_UNARY_BUILTINS = ["abs", "sign"];
48593
+ const SUPPORTED_UNARY_BUILTINS = ["abs", "sign", "floor", "ceil"];
48594
48594
  const SUPPORTED_SET_BUILTINS = ["min", "max"];
48595
48595
  exports.SUPPORTED_BUILTINS = SUPPORTED_BINARY_BUILTINS.concat(SUPPORTED_UNARY_BUILTINS, SUPPORTED_SET_BUILTINS);
48596
48596
  /**
@@ -48987,6 +48987,46 @@ class ForgeExprEvaluator extends AbstractParseTreeVisitor_1.AbstractParseTreeVis
48987
48987
  varNames.push(varName);
48988
48988
  quantifiedSets.push(varQuantifiedSets[varName]);
48989
48989
  }
48990
+ // `sum <decls> | <intExpr>`: accumulate the numeric body over every
48991
+ // binding of the quantified variables. Unlike the boolean quantifiers
48992
+ // below, the body evaluates to a number, so this needs its own loop --
48993
+ // and it must not use the boolean numeric-comparison optimization, which
48994
+ // skips body evaluation entirely.
48995
+ if (ctx.quant().SUM_TOK()) {
48996
+ const sumCombinations = getCombinations(quantifiedSets);
48997
+ const sumEnv = { env: {}, type: "quantDecl" };
48998
+ this.environmentStack.push(sumEnv);
48999
+ let total = 0;
49000
+ for (const tuple of sumCombinations) {
49001
+ if (isDisjoint) {
49002
+ const seen = new Set();
49003
+ let tupleDisjoint = true;
49004
+ for (const val of tuple) {
49005
+ if (seen.has(val)) {
49006
+ tupleDisjoint = false;
49007
+ break;
49008
+ }
49009
+ seen.add(val);
49010
+ }
49011
+ if (!tupleDisjoint) {
49012
+ continue;
49013
+ }
49014
+ }
49015
+ for (let j = 0; j < varNames.length; j++) {
49016
+ sumEnv.env[varNames[j]] = tuple[j];
49017
+ }
49018
+ const bodyValue = this.visit(barExpr);
49019
+ const bodyNumber = extractNumber(bodyValue);
49020
+ if (bodyNumber === undefined) {
49021
+ this.environmentStack.pop();
49022
+ throw new Error("Expected the expression after the bar in a `sum` to evaluate to a number!");
49023
+ }
49024
+ total += bodyNumber;
49025
+ }
49026
+ this.environmentStack.pop();
49027
+ this.cacheResult(ctx, freeVarsKey, total);
49028
+ return total;
49029
+ }
48990
49030
  // Try to optimize numeric comparisons
48991
49031
  let product;
48992
49032
  let useOptimizedPath = false;
@@ -49133,7 +49173,8 @@ class ForgeExprEvaluator extends AbstractParseTreeVisitor_1.AbstractParseTreeVis
49133
49173
  return value;
49134
49174
  }
49135
49175
  }
49136
- // TODO: don't have support for SUM_TOK yet
49176
+ // NOTE: SUM_TOK is handled above (it returns a number, not a boolean),
49177
+ // before this boolean-quantifier result logic.
49137
49178
  }
49138
49179
  // TODO: fix this!
49139
49180
  const childrenResults = this.visitChildren(ctx);
@@ -50367,7 +50408,7 @@ class ForgeExprEvaluator extends AbstractParseTreeVisitor_1.AbstractParseTreeVis
50367
50408
  result = arg1 * arg2;
50368
50409
  break;
50369
50410
  case "divide":
50370
- result = Math.floor(arg1 / arg2); // Integer division
50411
+ result = arg1 / arg2; // Real (floating-point) division
50371
50412
  break;
50372
50413
  case "remainder":
50373
50414
  result = arg1 % arg2;
@@ -50378,17 +50419,17 @@ class ForgeExprEvaluator extends AbstractParseTreeVisitor_1.AbstractParseTreeVis
50378
50419
  return result;
50379
50420
  }
50380
50421
  evaluateUnaryOperation(operation, args) {
50381
- if (!isSingleValue(args) || !isNumber(args)) {
50422
+ const v = extractNumber(args);
50423
+ if (v === undefined) {
50382
50424
  throw new Error(`Expected 1 argument for ${operation} that evaluates to a number.`);
50383
50425
  }
50384
- let v = args;
50385
50426
  // Possible unary operations:
50386
- //abs[]: returns the absolute value of value
50387
- //sign[]: returns 1 if value is > 0, 0 if value is 0, and -1 if value is < 0
50427
+ //abs[]: returns the absolute value of value
50428
+ //sign[]: returns 1 if value is > 0, 0 if value is 0, and -1 if value is < 0
50429
+ //floor[]: rounds value down to the nearest integer
50430
+ //ceil[]: rounds value up to the nearest integer
50388
50431
  if (operation === "abs") {
50389
- let res = Math.abs(v);
50390
- // Now adjust to the bitwidth
50391
- return res;
50432
+ return Math.abs(v);
50392
50433
  }
50393
50434
  else if (operation === "sign") {
50394
50435
  if (v > 0) {
@@ -50401,6 +50442,12 @@ class ForgeExprEvaluator extends AbstractParseTreeVisitor_1.AbstractParseTreeVis
50401
50442
  return 0;
50402
50443
  }
50403
50444
  }
50445
+ else if (operation === "floor") {
50446
+ return Math.floor(v);
50447
+ }
50448
+ else if (operation === "ceil") {
50449
+ return Math.ceil(v);
50450
+ }
50404
50451
  else {
50405
50452
  throw new Error(`Unsupported operation: ${operation}`);
50406
50453
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-graph-query",
3
- "version": "2.7.2",
3
+ "version": "2.8.1",
4
4
  "description": "TypeScript evaluator for Forge expressions with browser-compatible UMD bundle",
5
5
  "main": "dist/simple-graph-query.bundle.js",
6
6
  "types": "dist/index.d.ts",