@lokascript/framework 3.1.1 → 3.2.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.
package/dist/index.js CHANGED
@@ -1802,7 +1802,7 @@ var StringLiteralExtractor = class {
1802
1802
  }
1803
1803
  canExtract(input, position) {
1804
1804
  const char = input[position];
1805
- if (char === "'" && position > 0 && /[\p{L}\p{N}_)\]]/u.test(input[position - 1])) {
1805
+ if (char === "'" && position > 0 && /[\p{L}\p{M}\p{N}_)\]]/u.test(input[position - 1])) {
1806
1806
  return false;
1807
1807
  }
1808
1808
  return char === '"' || char === "'" || char === "`" || char === "\u201C" || // Chinese double quote open "
@@ -2362,11 +2362,18 @@ function convertRepeat(node) {
2362
2362
  roles.condition = convertValue(node.whileCondition);
2363
2363
  } else if (typeof node.untilEvent === "string") {
2364
2364
  variant = "until";
2365
- roles.condition = createLiteral(node.untilEvent);
2365
+ roles.loopType = createLiteral("until-event");
2366
+ roles.event = createLiteral(node.untilEvent);
2367
+ if (node.untilEventTarget && typeof node.untilEventTarget === "object") {
2368
+ roles.source = convertValue(node.untilEventTarget);
2369
+ }
2366
2370
  } else {
2367
2371
  variant = "forever";
2368
2372
  }
2369
- return createLoopNode("repeat", roles, variant, body);
2373
+ return createLoopNode("repeat", roles, variant, body, void 0, indexNameOf(node));
2374
+ }
2375
+ function indexNameOf(node) {
2376
+ return typeof node.indexName === "string" ? node.indexName : void 0;
2370
2377
  }
2371
2378
  function convertForEach(node) {
2372
2379
  const bodyNodes = Array.isArray(node.body) ? node.body : [];
@@ -2376,8 +2383,7 @@ function convertForEach(node) {
2376
2383
  roles.source = convertValue(node.collection);
2377
2384
  }
2378
2385
  const itemName = typeof node.itemName === "string" ? node.itemName : void 0;
2379
- const indexName = typeof node.indexName === "string" ? node.indexName : void 0;
2380
- return createLoopNode("repeat", roles, "for", body, itemName, indexName);
2386
+ return createLoopNode("repeat", roles, "for", body, itemName, indexNameOf(node));
2381
2387
  }
2382
2388
  function convertWhile(node) {
2383
2389
  const bodyNodes = Array.isArray(node.body) ? node.body : [];
@@ -2386,7 +2392,7 @@ function convertWhile(node) {
2386
2392
  if (node.condition && typeof node.condition === "object") {
2387
2393
  roles.condition = convertValue(node.condition);
2388
2394
  }
2389
- return createLoopNode("repeat", roles, "while", body);
2395
+ return createLoopNode("repeat", roles, "while", body, void 0, indexNameOf(node));
2390
2396
  }
2391
2397
  function convertValue(node) {
2392
2398
  switch (node.type) {
@@ -2713,28 +2719,64 @@ function convertCommand2(node) {
2713
2719
  roles
2714
2720
  };
2715
2721
  }
2722
+ function block(nodes) {
2723
+ return { type: "block", commands: (nodes ?? []).map(semanticNodeToRuntimeAST) };
2724
+ }
2716
2725
  function convertConditional(node) {
2726
+ const name = node.action === "unless" ? "unless" : "if";
2717
2727
  const conditionValue = node.roles.get("condition");
2728
+ if (!conditionValue) return { type: "command", name, args: [] };
2718
2729
  return {
2719
2730
  type: "command",
2720
- name: "if",
2721
- args: conditionValue ? [semanticValueToAST(conditionValue)] : [],
2722
- condition: conditionValue ? semanticValueToAST(conditionValue) : void 0,
2723
- thenBranch: (node.thenBranch ?? []).map(semanticNodeToRuntimeAST),
2724
- elseBranch: (node.elseBranch ?? []).map(semanticNodeToRuntimeAST)
2731
+ name,
2732
+ args: [
2733
+ semanticValueToAST(conditionValue),
2734
+ block(node.thenBranch),
2735
+ ...node.elseBranch && node.elseBranch.length > 0 ? [block(node.elseBranch)] : []
2736
+ ]
2725
2737
  };
2726
2738
  }
2739
+ var LOOP_FORMS = /* @__PURE__ */ new Set(["for", "times", "while", "until", "until-event", "forever"]);
2740
+ function valueText(value) {
2741
+ if (!value) return void 0;
2742
+ if (value.type === "literal") return String(value.value);
2743
+ if (value.type === "expression") return value.raw;
2744
+ if (value.type === "reference" || value.type === "selector") return value.value;
2745
+ return void 0;
2746
+ }
2727
2747
  function convertLoop(node) {
2728
- const countValue = node.roles.get("patient") || node.roles.get("count");
2729
- return {
2730
- type: "command",
2731
- name: "repeat",
2732
- args: countValue ? [semanticValueToAST(countValue)] : [],
2733
- loopVariant: node.loopVariant ?? "forever",
2734
- body: (node.body ?? []).map(semanticNodeToRuntimeAST),
2735
- loopVariable: node.loopVariable,
2736
- indexVariable: node.indexVariable
2748
+ const text = (value) => ({ type: "string", value });
2749
+ const operand = (role) => {
2750
+ const value = node.roles.get(role);
2751
+ return value ? semanticValueToAST(value) : void 0;
2737
2752
  };
2753
+ const declared = valueText(node.roles.get("loopType"));
2754
+ const form = node.action === "for" ? "for" : declared && LOOP_FORMS.has(declared) ? declared : node.loopVariant ?? "forever";
2755
+ const modifiers = { loopType: text(form) };
2756
+ const slot = (name, value) => {
2757
+ if (value) modifiers[name] = value;
2758
+ };
2759
+ switch (form) {
2760
+ case "for":
2761
+ if (node.loopVariable) slot("for", text(node.loopVariable));
2762
+ slot("in", operand("source"));
2763
+ break;
2764
+ case "times":
2765
+ slot("times", operand("quantity") ?? operand("patient") ?? operand("count"));
2766
+ break;
2767
+ case "while":
2768
+ case "until":
2769
+ slot(form, operand("condition"));
2770
+ break;
2771
+ case "until-event": {
2772
+ const event = valueText(node.roles.get("event"));
2773
+ if (event) slot("event", text(event));
2774
+ slot("from", operand("source"));
2775
+ break;
2776
+ }
2777
+ }
2778
+ if (node.indexVariable) slot("index", text(node.indexVariable));
2779
+ return { type: "command", name: "repeat", args: [block(node.body)], modifiers };
2738
2780
  }
2739
2781
  function semanticValueToAST(value) {
2740
2782
  switch (value.type) {
@@ -6493,7 +6535,7 @@ function accumulateIndented(statements, config) {
6493
6535
  const top = stack[stack.length - 1];
6494
6536
  if (top.indent >= targetIndent) {
6495
6537
  stack.pop();
6496
- const block = {
6538
+ const block2 = {
6497
6539
  type: top.type,
6498
6540
  ...top.name != null && { name: top.name },
6499
6541
  statements: top.stmts,
@@ -6502,9 +6544,9 @@ function accumulateIndented(statements, config) {
6502
6544
  indent: top.indent
6503
6545
  };
6504
6546
  if (stack.length > 0) {
6505
- stack[stack.length - 1].children.push(block);
6547
+ stack[stack.length - 1].children.push(block2);
6506
6548
  } else {
6507
- rootBlocks.push(block);
6549
+ rootBlocks.push(block2);
6508
6550
  }
6509
6551
  } else {
6510
6552
  break;