@almadar/evaluator 2.2.0 → 2.3.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.
@@ -261,19 +261,22 @@ declare function evalFn(args: SExpr[], _evaluate: Evaluator$2, _ctx: EvaluationC
261
261
  * Collection Operator Implementations
262
262
  *
263
263
  * Implements: map, filter, find, count, sum, first, last, nth, concat, includes, empty
264
+ *
265
+ * These short-form operators (map, filter, find) use @item/@index bindings,
266
+ * matching the Rust evaluator's approach.
264
267
  */
265
268
 
266
269
  type Evaluator$1 = (expr: SExpr, ctx: EvaluationContext) => unknown;
267
270
  /**
268
- * Evaluate map: ["map", collection, ["fn", varName, body]]
271
+ * Evaluate map: ["map", collection, expr_using_@item]
269
272
  */
270
273
  declare function evalMap(args: SExpr[], evaluate: Evaluator$1, ctx: EvaluationContext): unknown[];
271
274
  /**
272
- * Evaluate filter: ["filter", collection, ["fn", varName, predicate]]
275
+ * Evaluate filter: ["filter", collection, expr_using_@item]
273
276
  */
274
277
  declare function evalFilter(args: SExpr[], evaluate: Evaluator$1, ctx: EvaluationContext): unknown[];
275
278
  /**
276
- * Evaluate find: ["find", collection, ["fn", varName, predicate]]
279
+ * Evaluate find: ["find", collection, expr_using_@item]
277
280
  */
278
281
  declare function evalFind(args: SExpr[], evaluate: Evaluator$1, ctx: EvaluationContext): unknown;
279
282
  /**
@@ -281,7 +284,7 @@ declare function evalFind(args: SExpr[], evaluate: Evaluator$1, ctx: EvaluationC
281
284
  */
282
285
  declare function evalCount(args: SExpr[], evaluate: Evaluator$1, ctx: EvaluationContext): number;
283
286
  /**
284
- * Evaluate sum: ["sum", collection] or ["sum", collection, ["fn", varName, mapper]]
287
+ * Evaluate sum: ["sum", collection] or ["sum", collection, mapExpr_using_@item]
285
288
  */
286
289
  declare function evalSum(args: SExpr[], evaluate: Evaluator$1, ctx: EvaluationContext): number;
287
290
  /**
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { SExpr } from '@almadar/core';
2
2
  export { CORE_BINDINGS, CoreBinding, Expression, ExpressionSchema, ParsedBinding, SExpr, SExprAtom, SExprSchema, collectBindings, getArgs, getOperator, isBinding, isSExpr, isSExprAtom, isSExprCall, isValidBinding, parseBinding, sexpr, walkSExpr } from '@almadar/core';
3
- import { E as EvaluationContext } from './index-CTcWSDo1.js';
4
- export { c as createChildContext, a as createEffectContext, b as createMinimalContext, e as evalAbs, d as evalAdd, f as evalAnd, g as evalCallService, h as evalCeil, i as evalClamp, j as evalConcat, k as evalCount, l as evalDecrement, m as evalDespawn, n as evalDivide, o as evalDo, p as evalEmit, q as evalEmpty, r as evalEqual, s as evalFilter, t as evalFind, u as evalFirst, v as evalFloor, w as evalFn, x as evalGreaterThan, y as evalGreaterThanOrEqual, z as evalIf, A as evalIncludes, B as evalIncrement, C as evalLast, D as evalLessThan, F as evalLessThanOrEqual, G as evalLet, H as evalMap, I as evalMatches, J as evalMax, K as evalMin, L as evalModulo, M as evalMultiply, N as evalNavigate, O as evalNot, P as evalNotEqual, Q as evalNotify, R as evalNth, S as evalOr, T as evalPersist, U as evalRenderUI, V as evalRound, W as evalSet, X as evalSetDynamic, Y as evalSpawn, Z as evalSubtract, _ as evalSum, $ as evalWhen, a0 as resolveBinding } from './index-CTcWSDo1.js';
3
+ import { E as EvaluationContext } from './index-C-vYm4zW.js';
4
+ export { c as createChildContext, a as createEffectContext, b as createMinimalContext, e as evalAbs, d as evalAdd, f as evalAnd, g as evalCallService, h as evalCeil, i as evalClamp, j as evalConcat, k as evalCount, l as evalDecrement, m as evalDespawn, n as evalDivide, o as evalDo, p as evalEmit, q as evalEmpty, r as evalEqual, s as evalFilter, t as evalFind, u as evalFirst, v as evalFloor, w as evalFn, x as evalGreaterThan, y as evalGreaterThanOrEqual, z as evalIf, A as evalIncludes, B as evalIncrement, C as evalLast, D as evalLessThan, F as evalLessThanOrEqual, G as evalLet, H as evalMap, I as evalMatches, J as evalMax, K as evalMin, L as evalModulo, M as evalMultiply, N as evalNavigate, O as evalNot, P as evalNotEqual, Q as evalNotify, R as evalNth, S as evalOr, T as evalPersist, U as evalRenderUI, V as evalRound, W as evalSet, X as evalSetDynamic, Y as evalSpawn, Z as evalSubtract, _ as evalSum, $ as evalWhen, a0 as resolveBinding } from './index-C-vYm4zW.js';
5
5
 
6
6
  /**
7
7
  * S-Expression Evaluator
package/dist/index.js CHANGED
@@ -298,44 +298,26 @@ function evalFn(args, _evaluate, _ctx) {
298
298
  }
299
299
 
300
300
  // operators/collections.ts
301
+ function withItem(expr, evaluate2, ctx, item, index) {
302
+ const locals = /* @__PURE__ */ new Map();
303
+ locals.set("item", item);
304
+ locals.set("index", index);
305
+ return evaluate2(expr, createChildContext(ctx, locals));
306
+ }
301
307
  function evalMap(args, evaluate2, ctx) {
302
308
  const collection = toArray(evaluate2(args[0], ctx));
303
- const fnExpr = args[1];
304
- const params = fnExpr[1];
305
- const body = fnExpr[2];
306
- const varName = typeof params === "string" ? params : params[0];
307
- return collection.map((item) => {
308
- const locals = /* @__PURE__ */ new Map();
309
- locals.set(varName, item);
310
- const childCtx = createChildContext(ctx, locals);
311
- return evaluate2(body, childCtx);
312
- });
309
+ const mapExpr = args[1];
310
+ return collection.map((item, i) => withItem(mapExpr, evaluate2, ctx, item, i));
313
311
  }
314
312
  function evalFilter(args, evaluate2, ctx) {
315
313
  const collection = toArray(evaluate2(args[0], ctx));
316
- const fnExpr = args[1];
317
- const params = fnExpr[1];
318
- const body = fnExpr[2];
319
- const varName = typeof params === "string" ? params : params[0];
320
- return collection.filter((item) => {
321
- const locals = /* @__PURE__ */ new Map();
322
- locals.set(varName, item);
323
- const childCtx = createChildContext(ctx, locals);
324
- return Boolean(evaluate2(body, childCtx));
325
- });
314
+ const predExpr = args[1];
315
+ return collection.filter((item, i) => Boolean(withItem(predExpr, evaluate2, ctx, item, i)));
326
316
  }
327
317
  function evalFind(args, evaluate2, ctx) {
328
318
  const collection = toArray(evaluate2(args[0], ctx));
329
- const fnExpr = args[1];
330
- const params = fnExpr[1];
331
- const body = fnExpr[2];
332
- const varName = typeof params === "string" ? params : params[0];
333
- return collection.find((item) => {
334
- const locals = /* @__PURE__ */ new Map();
335
- locals.set(varName, item);
336
- const childCtx = createChildContext(ctx, locals);
337
- return Boolean(evaluate2(body, childCtx));
338
- });
319
+ const predExpr = args[1];
320
+ return collection.find((item, i) => Boolean(withItem(predExpr, evaluate2, ctx, item, i)));
339
321
  }
340
322
  function evalCount(args, evaluate2, ctx) {
341
323
  const collection = toArray(evaluate2(args[0], ctx));
@@ -346,15 +328,13 @@ function evalSum(args, evaluate2, ctx) {
346
328
  if (args.length === 1) {
347
329
  return collection.reduce((sum, item) => sum + toNumber2(item), 0);
348
330
  }
349
- const fnExpr = args[1];
350
- const params = fnExpr[1];
351
- const body = fnExpr[2];
352
- const varName = typeof params === "string" ? params : params[0];
353
- return collection.reduce((sum, item) => {
331
+ const mapExpr = args[1];
332
+ return collection.reduce((sum, item, i) => {
354
333
  const locals = /* @__PURE__ */ new Map();
355
- locals.set(varName, item);
334
+ locals.set("item", item);
335
+ locals.set("index", i);
356
336
  const childCtx = createChildContext(ctx, locals);
357
- return sum + toNumber2(evaluate2(body, childCtx));
337
+ return sum + toNumber2(evaluate2(mapExpr, childCtx));
358
338
  }, 0);
359
339
  }
360
340
  function evalFirst(args, evaluate2, ctx) {
@@ -520,10 +500,23 @@ function evalCallService(args, evaluate2, ctx) {
520
500
  console.error(`Service call ${service}.${method} failed:`, err);
521
501
  });
522
502
  }
503
+ function evaluateNestedProps(obj, evaluate2, ctx) {
504
+ const result = {};
505
+ for (const [key, value] of Object.entries(obj)) {
506
+ if (Array.isArray(value) && value.length > 0 && typeof value[0] === "string") {
507
+ result[key] = evaluate2(value, ctx);
508
+ } else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
509
+ result[key] = evaluateNestedProps(value, evaluate2, ctx);
510
+ } else {
511
+ result[key] = value;
512
+ }
513
+ }
514
+ return result;
515
+ }
523
516
  function evalRenderUI(args, evaluate2, ctx) {
524
517
  const slot = args[0];
525
518
  const pattern = evaluate2(args[1], ctx);
526
- const props = args.length > 2 ? evaluate2(args[2], ctx) : void 0;
519
+ const rawProps = args.length > 2 ? args[2] : void 0;
527
520
  const priority = args.length > 3 ? evaluate2(args[3], ctx) : void 0;
528
521
  if (!ctx.renderUI) {
529
522
  console.warn("No renderUI handler in context for render-ui effect");
@@ -533,6 +526,7 @@ function evalRenderUI(args, evaluate2, ctx) {
533
526
  ctx.renderUI(slot, { type: "clear" }, void 0, priority);
534
527
  return;
535
528
  }
529
+ const props = rawProps ? evaluateNestedProps(rawProps, evaluate2, ctx) : void 0;
536
530
  ctx.renderUI(slot, pattern, props, priority);
537
531
  }
538
532
  function evalSetDynamic(args, evaluate2, ctx) {
@@ -825,29 +819,37 @@ function evalStrTruncate(args, evaluate2, ctx) {
825
819
  }
826
820
 
827
821
  // std/array.ts
828
- function evalLambda(lambdaExpr, evaluate2, ctx, ...values) {
829
- if (!isSExpr(lambdaExpr) || getOperator(lambdaExpr) !== "fn") {
830
- return evaluate2(lambdaExpr, ctx);
831
- }
832
- const args = getArgs(lambdaExpr);
833
- const params = args[0];
834
- const body = args[1];
835
- const newLocals = /* @__PURE__ */ new Map();
836
- if (Array.isArray(params)) {
837
- const paramNames = params;
838
- values.forEach((v, i) => {
839
- if (paramNames[i]) {
840
- const paramName = paramNames[i];
841
- const key = paramName.startsWith("@") ? paramName.slice(1) : paramName;
842
- newLocals.set(key, v);
843
- }
844
- });
845
- } else if (typeof params === "string") {
846
- const paramName = params.startsWith("@") ? params.slice(1) : params;
847
- newLocals.set(paramName, values[0]);
822
+ function evalWithItem(expr, evaluate2, ctx, item, index) {
823
+ const locals = /* @__PURE__ */ new Map();
824
+ locals.set("item", item);
825
+ locals.set("index", index);
826
+ const childCtx = createChildContext(ctx, locals);
827
+ return evaluate2(expr, childCtx);
828
+ }
829
+ function evalReduceLambda(lambdaExpr, evaluate2, ctx, acc, item) {
830
+ const locals = /* @__PURE__ */ new Map();
831
+ if (isSExpr(lambdaExpr) && getOperator(lambdaExpr) === "fn") {
832
+ const fnArgs = getArgs(lambdaExpr);
833
+ const params = fnArgs[0];
834
+ const body = fnArgs[1];
835
+ if (Array.isArray(params)) {
836
+ const paramNames = params;
837
+ const values = [acc, item];
838
+ paramNames.forEach((p, i) => {
839
+ const key = p.startsWith("@") ? p.slice(1) : p;
840
+ locals.set(key, values[i]);
841
+ });
842
+ } else if (typeof params === "string") {
843
+ const key = params.startsWith("@") ? params.slice(1) : params;
844
+ locals.set(key, acc);
845
+ }
846
+ const childCtx2 = createChildContext(ctx, locals);
847
+ return evaluate2(body, childCtx2);
848
848
  }
849
- const childCtx = createChildContext(ctx, newLocals);
850
- return evaluate2(body, childCtx);
849
+ locals.set("acc", acc);
850
+ locals.set("item", item);
851
+ const childCtx = createChildContext(ctx, locals);
852
+ return evaluate2(lambdaExpr, childCtx);
851
853
  }
852
854
  function evalArrayLen(args, evaluate2, ctx) {
853
855
  const arr = evaluate2(args[0], ctx);
@@ -981,53 +983,53 @@ function evalArrayIndexOf(args, evaluate2, ctx) {
981
983
  }
982
984
  function evalArrayFind(args, evaluate2, ctx) {
983
985
  const arr = evaluate2(args[0], ctx);
984
- const lambda = args[1];
985
- return (arr ?? []).find((item) => evalLambda(lambda, evaluate2, ctx, item));
986
+ const predExpr = args[1];
987
+ return (arr ?? []).find((item, i) => evalWithItem(predExpr, evaluate2, ctx, item, i));
986
988
  }
987
989
  function evalArrayFindIndex(args, evaluate2, ctx) {
988
990
  const arr = evaluate2(args[0], ctx);
989
- const lambda = args[1];
990
- return (arr ?? []).findIndex((item) => evalLambda(lambda, evaluate2, ctx, item));
991
+ const predExpr = args[1];
992
+ return (arr ?? []).findIndex((item, i) => evalWithItem(predExpr, evaluate2, ctx, item, i));
991
993
  }
992
994
  function evalArrayFilter(args, evaluate2, ctx) {
993
995
  const arr = evaluate2(args[0], ctx);
994
- const lambda = args[1];
995
- return (arr ?? []).filter((item) => evalLambda(lambda, evaluate2, ctx, item));
996
+ const predExpr = args[1];
997
+ return (arr ?? []).filter((item, i) => evalWithItem(predExpr, evaluate2, ctx, item, i));
996
998
  }
997
999
  function evalArrayReject(args, evaluate2, ctx) {
998
1000
  const arr = evaluate2(args[0], ctx);
999
- const lambda = args[1];
1000
- return (arr ?? []).filter((item) => !evalLambda(lambda, evaluate2, ctx, item));
1001
+ const predExpr = args[1];
1002
+ return (arr ?? []).filter((item, i) => !evalWithItem(predExpr, evaluate2, ctx, item, i));
1001
1003
  }
1002
1004
  function evalArrayMap(args, evaluate2, ctx) {
1003
1005
  const arr = evaluate2(args[0], ctx);
1004
- const lambda = args[1];
1005
- return (arr ?? []).map((item) => evalLambda(lambda, evaluate2, ctx, item));
1006
+ const mapExpr = args[1];
1007
+ return (arr ?? []).map((item, i) => evalWithItem(mapExpr, evaluate2, ctx, item, i));
1006
1008
  }
1007
1009
  function evalArrayReduce(args, evaluate2, ctx) {
1008
1010
  const arr = evaluate2(args[0], ctx);
1009
- const lambda = args[1];
1010
- const init = evaluate2(args[2], ctx);
1011
+ const init = evaluate2(args[1], ctx);
1012
+ const reducerExpr = args[2];
1011
1013
  return (arr ?? []).reduce(
1012
- (acc, item) => evalLambda(lambda, evaluate2, ctx, acc, item),
1014
+ (acc, item) => evalReduceLambda(reducerExpr, evaluate2, ctx, acc, item),
1013
1015
  init
1014
1016
  );
1015
1017
  }
1016
1018
  function evalArrayEvery(args, evaluate2, ctx) {
1017
1019
  const arr = evaluate2(args[0], ctx);
1018
- const lambda = args[1];
1019
- return (arr ?? []).every((item) => Boolean(evalLambda(lambda, evaluate2, ctx, item)));
1020
+ const predExpr = args[1];
1021
+ return (arr ?? []).every((item, i) => Boolean(evalWithItem(predExpr, evaluate2, ctx, item, i)));
1020
1022
  }
1021
1023
  function evalArraySome(args, evaluate2, ctx) {
1022
1024
  const arr = evaluate2(args[0], ctx);
1023
- const lambda = args[1];
1024
- return (arr ?? []).some((item) => Boolean(evalLambda(lambda, evaluate2, ctx, item)));
1025
+ const predExpr = args[1];
1026
+ return (arr ?? []).some((item, i) => Boolean(evalWithItem(predExpr, evaluate2, ctx, item, i)));
1025
1027
  }
1026
1028
  function evalArrayCount(args, evaluate2, ctx) {
1027
1029
  const arr = evaluate2(args[0], ctx);
1028
1030
  if (args.length > 1) {
1029
- const lambda = args[1];
1030
- return (arr ?? []).filter((item) => evalLambda(lambda, evaluate2, ctx, item)).length;
1031
+ const predExpr = args[1];
1032
+ return (arr ?? []).filter((item, i) => evalWithItem(predExpr, evaluate2, ctx, item, i)).length;
1031
1033
  }
1032
1034
  return arr?.length ?? 0;
1033
1035
  }
@@ -1084,16 +1086,16 @@ function evalArrayGroupBy(args, evaluate2, ctx) {
1084
1086
  }
1085
1087
  function evalArrayPartition(args, evaluate2, ctx) {
1086
1088
  const arr = evaluate2(args[0], ctx);
1087
- const lambda = args[1];
1089
+ const predExpr = args[1];
1088
1090
  const matches = [];
1089
1091
  const nonMatches = [];
1090
- for (const item of arr ?? []) {
1091
- if (evalLambda(lambda, evaluate2, ctx, item)) {
1092
+ (arr ?? []).forEach((item, i) => {
1093
+ if (evalWithItem(predExpr, evaluate2, ctx, item, i)) {
1092
1094
  matches.push(item);
1093
1095
  } else {
1094
1096
  nonMatches.push(item);
1095
1097
  }
1096
- }
1098
+ });
1097
1099
  return [matches, nonMatches];
1098
1100
  }
1099
1101
  function evalArrayTake(args, evaluate2, ctx) {
@@ -1118,7 +1120,7 @@ function evalArrayDropLast(args, evaluate2, ctx) {
1118
1120
  }
1119
1121
 
1120
1122
  // std/object.ts
1121
- function evalLambda2(lambdaExpr, evaluate2, ctx, ...values) {
1123
+ function evalLambda(lambdaExpr, evaluate2, ctx, ...values) {
1122
1124
  if (!isSExpr(lambdaExpr) || getOperator(lambdaExpr) !== "fn") {
1123
1125
  return evaluate2(lambdaExpr, ctx);
1124
1126
  }
@@ -1258,7 +1260,7 @@ function evalObjectMapValues(args, evaluate2, ctx) {
1258
1260
  const lambda = args[1];
1259
1261
  const result = {};
1260
1262
  for (const [key, value] of Object.entries(obj ?? {})) {
1261
- result[key] = evalLambda2(lambda, evaluate2, ctx, value);
1263
+ result[key] = evalLambda(lambda, evaluate2, ctx, value);
1262
1264
  }
1263
1265
  return result;
1264
1266
  }
@@ -1267,7 +1269,7 @@ function evalObjectMapKeys(args, evaluate2, ctx) {
1267
1269
  const lambda = args[1];
1268
1270
  const result = {};
1269
1271
  for (const [key, value] of Object.entries(obj ?? {})) {
1270
- const newKey = String(evalLambda2(lambda, evaluate2, ctx, key));
1272
+ const newKey = String(evalLambda(lambda, evaluate2, ctx, key));
1271
1273
  result[newKey] = value;
1272
1274
  }
1273
1275
  return result;
@@ -1277,7 +1279,7 @@ function evalObjectFilter(args, evaluate2, ctx) {
1277
1279
  const lambda = args[1];
1278
1280
  const result = {};
1279
1281
  for (const [key, value] of Object.entries(obj ?? {})) {
1280
- if (evalLambda2(lambda, evaluate2, ctx, key, value)) {
1282
+ if (evalLambda(lambda, evaluate2, ctx, key, value)) {
1281
1283
  result[key] = value;
1282
1284
  }
1283
1285
  }