@barefootjs/go-template 0.1.2 → 0.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.
@@ -74,6 +74,7 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
74
74
  private options;
75
75
  private inLoop;
76
76
  private loopParamStack;
77
+ private loopVarRefCount;
77
78
  private errors;
78
79
  private propsObjectName;
79
80
  /**
@@ -84,6 +85,7 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
84
85
  * follow-up).
85
86
  */
86
87
  private restPropsName;
88
+ private templateVarCounter;
87
89
  /** Local type names resolved from typeDefinitions (populated during generateTypes) */
88
90
  private localTypeNames;
89
91
  /** Local type aliases mapping type name to base type (e.g., Filter → 'string') */
@@ -481,13 +483,13 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
481
483
  */
482
484
  private renderHigherOrderExpr;
483
485
  /**
484
- * Render find()/findIndex() with complex predicates using {{range}}{{if}}...{{break}} blocks.
485
- * Falls back from bf_find/bf_find_index when extractEqualityPredicate returns null.
486
- * Reuses renderFilterExpr for condition rendering.
486
+ * Render find/findIndex/findLast/findLastIndex with complex predicates
487
+ * using range/if blocks. Falls back from bf_find/bf_find_last helpers
488
+ * when extractEqualityPredicate returns null.
487
489
  *
488
- * @param expr - The higher-order find/findIndex expression
489
- * @param renderArray - Function to render the array expression
490
- * @param propertyAccess - Optional property to access on the found element (for find().property)
490
+ * find/findIndex use break on first match (forward scan).
491
+ * findLast/findLastIndex iterate forward and keep overwriting a result
492
+ * variable; the final value is the last match.
491
493
  */
492
494
  private renderFindTemplateBlock;
493
495
  /**
@@ -525,6 +527,14 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
525
527
  * Check if expression needs parentheses when used in and/or.
526
528
  */
527
529
  private needsParens;
530
+ /**
531
+ * Split a rendered template block into preamble + final expression.
532
+ * The last `{{...}}` must be a variable reference (`$bf_rN` or
533
+ * `$bf_result`). Control tokens like `{{end}}` or `{{break}}` are
534
+ * rejected — those template blocks (e.g. find's range/break form)
535
+ * can't be composed in binary/logical expressions.
536
+ */
537
+ private splitPreamble;
528
538
  /**
529
539
  * Render block body filter into a single Go template condition.
530
540
  *
@@ -606,9 +616,6 @@ export declare class GoTemplateAdapter extends BaseAdapter implements ParsedExpr
606
616
  * that must be emitted before the {{if}} (e.g., every/some range blocks).
607
617
  */
608
618
  private convertConditionToGo;
609
- /**
610
- * Render a ParsedExpr as a Go template condition.
611
- */
612
619
  private renderConditionExpr;
613
620
  renderLoop(loop: IRLoop): string;
614
621
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"go-template-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/go-template-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"go-template-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/go-template-adapter.ts"],"names":[],"mappings":"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"}
@@ -80,9 +80,11 @@ class GoTemplateAdapter extends BaseAdapter {
80
80
  options;
81
81
  inLoop = false;
82
82
  loopParamStack = [];
83
+ loopVarRefCount = new Map;
83
84
  errors = [];
84
85
  propsObjectName = null;
85
86
  restPropsName = null;
87
+ templateVarCounter = 0;
86
88
  localTypeNames = new Set;
87
89
  localTypeAliases = new Map;
88
90
  usesHtmlTemplate = false;
@@ -97,6 +99,7 @@ class GoTemplateAdapter extends BaseAdapter {
97
99
  generate(ir, options) {
98
100
  this.componentName = ir.metadata.componentName;
99
101
  this.errors = [];
102
+ this.templateVarCounter = 0;
100
103
  this.propsObjectName = ir.metadata.propsObjectName;
101
104
  this.restPropsName = ir.metadata.restPropsName ?? null;
102
105
  if (!options?.siblingTemplatesRegistered) {
@@ -436,7 +439,7 @@ ${goFields.join(`
436
439
  lines.push("\tScopeID string // Optional: if empty, random ID is generated");
437
440
  lines.push("\tBfParent string // Optional: parent scope id");
438
441
  lines.push("\tBfMount string // Optional: slot id in parent");
439
- const staticNested = nestedComponents.filter((n) => !n.isDynamic);
442
+ const inputNested = nestedComponents.filter((n) => !n.isDynamic || n.isPropDerived);
440
443
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
441
444
  for (const param of ir.metadata.propsParams) {
442
445
  const fieldName = this.capitalizeFieldName(param.name);
@@ -445,7 +448,7 @@ ${goFields.join(`
445
448
  const goType = propTypeOverrides.get(param.name) ?? this.typeInfoToGo(param.type, param.defaultValue);
446
449
  lines.push(` ${fieldName} ${goType}`);
447
450
  }
448
- for (const nested of staticNested) {
451
+ for (const nested of inputNested) {
449
452
  lines.push(` ${nested.name}s []${nested.name}Input`);
450
453
  }
451
454
  const restPropsName = ir.metadata.restPropsName;
@@ -521,7 +524,7 @@ ${goFields.join(`
521
524
  lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
522
525
  }
523
526
  for (const nested of nestedComponents) {
524
- if (nested.isDynamic) {
527
+ if (nested.isDynamic && !nested.isPropDerived) {
525
528
  lines.push(` ${nested.name}s []${nested.name}Props \`json:"-"\``);
526
529
  } else {
527
530
  const jsonTag = this.toJsonTag(`${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`);
@@ -542,9 +545,9 @@ ${goFields.join(`
542
545
  generateNewPropsFunction(lines, ir, componentName, nestedComponents, spreadSlots) {
543
546
  const inputTypeName = `${componentName}Input`;
544
547
  const propsTypeName = `${componentName}Props`;
545
- const dynamicNested = nestedComponents.filter((n) => n.isDynamic);
548
+ const signalDynamicNested = nestedComponents.filter((n) => n.isDynamic && !n.isPropDerived);
546
549
  lines.push(`// New${componentName}Props creates ${propsTypeName} from ${inputTypeName}.`);
547
- for (const nested of dynamicNested) {
550
+ for (const nested of signalDynamicNested) {
548
551
  const arrayField = `${nested.name}s`;
549
552
  lines.push(`//`);
550
553
  lines.push(`// NOTE: \`${arrayField}\` is populated by the route handler, not by`);
@@ -566,7 +569,7 @@ ${goFields.join(`
566
569
  lines.push(` scopeID = "${componentName}_" + randomID(6)`);
567
570
  lines.push("\t}");
568
571
  lines.push("");
569
- const staticNested = nestedComponents.filter((n) => !n.isDynamic);
572
+ const staticNested = nestedComponents.filter((n) => !n.isDynamic || n.isPropDerived);
570
573
  if (staticNested.length > 0) {
571
574
  for (const nested of staticNested) {
572
575
  const varName = `${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`;
@@ -714,7 +717,8 @@ ${goFields.join(`
714
717
  if (!result.some((c) => c.name === loop.childComponent.name)) {
715
718
  result.push({
716
719
  ...loop.childComponent,
717
- isDynamic: !loop.isStaticArray
720
+ isDynamic: !loop.isStaticArray,
721
+ isPropDerived: !!loop.isPropDerivedArray
718
722
  });
719
723
  }
720
724
  }
@@ -1531,13 +1535,18 @@ ${goFields.join(`
1531
1535
  return emitParsedExpr(expr, this);
1532
1536
  }
1533
1537
  identifier(name) {
1538
+ const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
1539
+ if (currentLoopParam && name === currentLoopParam)
1540
+ return ".";
1541
+ if (this.loopVarRefCount.has(name))
1542
+ return `$${name}`;
1534
1543
  return `.${this.capitalizeFieldName(name)}`;
1535
1544
  }
1536
1545
  literal(value, literalType) {
1537
1546
  if (literalType === "string")
1538
1547
  return `"${value}"`;
1539
1548
  if (literalType === "null")
1540
- return '""';
1549
+ return "nil";
1541
1550
  return String(value);
1542
1551
  }
1543
1552
  call(callee, args, emit) {
@@ -1573,7 +1582,7 @@ ${goFields.join(`
1573
1582
  if (result)
1574
1583
  return result;
1575
1584
  }
1576
- if (object.kind === "higher-order" && object.method === "find") {
1585
+ if (object.kind === "higher-order" && (object.method === "find" || object.method === "findLast")) {
1577
1586
  const findResult = this.renderHigherOrderExpr(object, emit);
1578
1587
  if (findResult) {
1579
1588
  return `{{with ${findResult}}}{{.${this.capitalizeFieldName(property)}}}{{end}}`;
@@ -1677,7 +1686,7 @@ ${goFields.join(`
1677
1686
  const result = this.renderHigherOrderExpr(reconstructed, emit);
1678
1687
  if (result)
1679
1688
  return result;
1680
- if (method === "find" || method === "findIndex") {
1689
+ if (method === "find" || method === "findIndex" || method === "findLast" || method === "findLastIndex") {
1681
1690
  const templateBlock = this.renderFindTemplateBlock(reconstructed, emit);
1682
1691
  if (templateBlock)
1683
1692
  return templateBlock;
@@ -1817,12 +1826,17 @@ ${goFields.join(`
1817
1826
  const value = negated ? "false" : "true";
1818
1827
  return `bf_filter ${arrayExpr} "${field}" ${value}`;
1819
1828
  }
1820
- if (expr.method === "find" || expr.method === "findIndex") {
1829
+ if (expr.method === "find" || expr.method === "findIndex" || expr.method === "findLast" || expr.method === "findLastIndex") {
1821
1830
  const eqPred = this.extractEqualityPredicate(expr.predicate, expr.param, (e) => this.renderParsedExpr(e));
1822
1831
  if (!eqPred)
1823
1832
  return null;
1824
- const func = expr.method === "find" ? "bf_find" : "bf_find_index";
1825
- return `${func} ${arrayExpr} "${eqPred.field}" ${eqPred.value}`;
1833
+ const funcMap = {
1834
+ find: "bf_find",
1835
+ findIndex: "bf_find_index",
1836
+ findLast: "bf_find_last",
1837
+ findLastIndex: "bf_find_last_index"
1838
+ };
1839
+ return `${funcMap[expr.method]} ${arrayExpr} "${eqPred.field}" ${eqPred.value}`;
1826
1840
  }
1827
1841
  return null;
1828
1842
  }
@@ -1838,6 +1852,15 @@ ${goFields.join(`
1838
1852
  if (expr.method === "findIndex") {
1839
1853
  return `{{range $i, $_ := ${arrayExpr}}}{{if ${condition}}}{{$i}}{{break}}{{end}}{{end}}`;
1840
1854
  }
1855
+ if (expr.method === "findLast") {
1856
+ const v = `$bf_r${this.templateVarCounter++}`;
1857
+ const capture = propertyAccess ? `.${propertyAccess}` : ".";
1858
+ return `{{${v} := ""}}{{range ${arrayExpr}}}{{if ${condition}}}{{${v} = ${capture}}}{{end}}{{end}}{{${v}}}`;
1859
+ }
1860
+ if (expr.method === "findLastIndex") {
1861
+ const v = `$bf_r${this.templateVarCounter++}`;
1862
+ return `{{${v} := -1}}{{range $i, $_ := ${arrayExpr}}}{{if ${condition}}}{{${v} = $i}}{{end}}{{end}}{{${v}}}`;
1863
+ }
1841
1864
  return null;
1842
1865
  }
1843
1866
  renderEverySomeTemplateBlock(expr, renderArray) {
@@ -1846,11 +1869,13 @@ ${goFields.join(`
1846
1869
  if (condition.includes("[UNSUPPORTED"))
1847
1870
  return null;
1848
1871
  if (expr.method === "every") {
1872
+ const v = `$bf_r${this.templateVarCounter++}`;
1849
1873
  const negated = this.negateGoCondition(condition);
1850
- return `{{$bf_result := true}}{{range ${arrayExpr}}}{{if ${negated}}}{{$bf_result = false}}{{break}}{{end}}{{end}}{{$bf_result}}`;
1874
+ return `{{${v} := true}}{{range ${arrayExpr}}}{{if ${negated}}}{{${v} = false}}{{break}}{{end}}{{end}}{{${v}}}`;
1851
1875
  }
1852
1876
  if (expr.method === "some") {
1853
- return `{{$bf_result := false}}{{range ${arrayExpr}}}{{if ${condition}}}{{$bf_result = true}}{{break}}{{end}}{{end}}{{$bf_result}}`;
1877
+ const v = `$bf_r${this.templateVarCounter++}`;
1878
+ return `{{${v} := false}}{{range ${arrayExpr}}}{{if ${condition}}}{{${v} = true}}{{break}}{{end}}{{end}}{{${v}}}`;
1854
1879
  }
1855
1880
  return null;
1856
1881
  }
@@ -1879,6 +1904,22 @@ ${goFields.join(`
1879
1904
  needsParens(expr) {
1880
1905
  return expr.kind === "logical" || expr.kind === "unary" || expr.kind === "conditional";
1881
1906
  }
1907
+ splitPreamble(rendered) {
1908
+ if (!rendered.includes("{{"))
1909
+ return null;
1910
+ const lastOpen = rendered.lastIndexOf("{{");
1911
+ const lastClose = rendered.lastIndexOf("}}");
1912
+ if (lastOpen >= 0 && lastClose > lastOpen) {
1913
+ const candidate = rendered.substring(lastOpen + 2, lastClose);
1914
+ if (!candidate.startsWith("$"))
1915
+ return null;
1916
+ return {
1917
+ preamble: rendered.substring(0, lastOpen),
1918
+ expr: candidate
1919
+ };
1920
+ }
1921
+ return null;
1922
+ }
1882
1923
  renderBlockBodyCondition(statements, param) {
1883
1924
  const localVarMap = new Map;
1884
1925
  const paths = this.collectReturnPaths(statements, [], localVarMap, param);
@@ -1999,7 +2040,7 @@ ${goFields.join(`
1999
2040
  return `"${expr.value}"`;
2000
2041
  }
2001
2042
  if (expr.literalType === "null") {
2002
- return '""';
2043
+ return "nil";
2003
2044
  }
2004
2045
  return String(expr.value);
2005
2046
  case "member": {
@@ -2276,138 +2317,141 @@ Options:
2276
2317
  });
2277
2318
  return { condition: `false`, preamble: "" };
2278
2319
  }
2279
- const rendered = this.renderConditionExpr(parsed);
2280
- if (rendered.startsWith("{{")) {
2281
- const lastOpen = rendered.lastIndexOf("{{");
2282
- const lastClose = rendered.lastIndexOf("}}");
2283
- if (lastOpen >= 0 && lastClose > lastOpen) {
2284
- const preamble = rendered.substring(0, lastOpen);
2285
- const condition = rendered.substring(lastOpen + 2, lastClose);
2286
- return { condition, preamble };
2287
- }
2288
- }
2289
- return { condition: rendered, preamble: "" };
2320
+ const { preamble, expr: condition } = this.renderConditionExpr(parsed);
2321
+ return { condition, preamble };
2290
2322
  }
2291
2323
  renderConditionExpr(expr) {
2324
+ const plain = (e) => ({ preamble: "", expr: e });
2292
2325
  switch (expr.kind) {
2293
2326
  case "identifier":
2294
2327
  {
2295
2328
  const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
2296
2329
  if (currentLoopParam && expr.name === currentLoopParam) {
2297
- return ".";
2330
+ return plain(".");
2331
+ }
2332
+ if (this.loopVarRefCount.has(expr.name)) {
2333
+ return plain(`$${expr.name}`);
2298
2334
  }
2299
2335
  }
2300
- return `.${this.capitalizeFieldName(expr.name)}`;
2336
+ return plain(`.${this.capitalizeFieldName(expr.name)}`);
2301
2337
  case "literal":
2302
- if (expr.literalType === "string") {
2303
- return `"${expr.value}"`;
2304
- }
2305
- if (expr.literalType === "null") {
2306
- return '""';
2307
- }
2308
- return String(expr.value);
2338
+ if (expr.literalType === "string")
2339
+ return plain(`"${expr.value}"`);
2340
+ if (expr.literalType === "null")
2341
+ return plain("nil");
2342
+ return plain(String(expr.value));
2309
2343
  case "call": {
2310
2344
  if (expr.callee.kind === "identifier" && expr.args.length === 0) {
2311
- return `.${this.capitalizeFieldName(expr.callee.name)}`;
2345
+ return plain(`.${this.capitalizeFieldName(expr.callee.name)}`);
2312
2346
  }
2313
- return this.renderParsedExpr(expr);
2347
+ return plain(this.renderParsedExpr(expr));
2314
2348
  }
2315
2349
  case "member": {
2316
2350
  if (expr.property === "length" && expr.object.kind === "higher-order") {
2317
- const result = this.renderFilterLengthExpr(expr.object, (e) => this.renderConditionExpr(e));
2318
- if (result) {
2319
- return result;
2320
- }
2351
+ const result = this.renderFilterLengthExpr(expr.object, (e) => this.renderConditionExpr(e).expr);
2352
+ if (result)
2353
+ return plain(result);
2321
2354
  }
2322
2355
  if (expr.object.kind === "identifier" && this.propsObjectName && expr.object.name === this.propsObjectName) {
2323
- return `.${this.capitalizeFieldName(expr.property)}`;
2356
+ return plain(`.${this.capitalizeFieldName(expr.property)}`);
2324
2357
  }
2325
2358
  {
2326
2359
  const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
2327
2360
  if (expr.object.kind === "identifier" && currentLoopParam && expr.object.name === currentLoopParam) {
2328
- return `.${this.capitalizeFieldName(expr.property)}`;
2361
+ return plain(`.${this.capitalizeFieldName(expr.property)}`);
2329
2362
  }
2330
2363
  }
2331
2364
  const obj = this.renderConditionExpr(expr.object);
2332
2365
  if (expr.property === "length") {
2333
- return `len ${obj}`;
2366
+ return { preamble: obj.preamble, expr: `len ${obj.expr}` };
2334
2367
  }
2335
- return `${obj}.${this.capitalizeFieldName(expr.property)}`;
2368
+ return { preamble: obj.preamble, expr: `${obj.expr}.${this.capitalizeFieldName(expr.property)}` };
2336
2369
  }
2337
2370
  case "binary": {
2338
2371
  const leftNeedsParens = this.needsParensInGoTemplate(expr.left);
2339
- let left = this.renderConditionExpr(expr.left);
2340
- if (leftNeedsParens) {
2341
- left = `(${left})`;
2342
- }
2372
+ const leftResult = this.renderConditionExpr(expr.left);
2373
+ const left = leftNeedsParens ? `(${leftResult.expr})` : leftResult.expr;
2343
2374
  const rightNeedsParens = this.needsParensInGoTemplate(expr.right);
2344
- let right = this.renderConditionExpr(expr.right);
2345
- if (rightNeedsParens) {
2346
- right = `(${right})`;
2347
- }
2375
+ const rightResult = this.renderConditionExpr(expr.right);
2376
+ const right = rightNeedsParens ? `(${rightResult.expr})` : rightResult.expr;
2377
+ const preamble = leftResult.preamble + rightResult.preamble;
2378
+ let result;
2348
2379
  switch (expr.op) {
2349
2380
  case "===":
2350
2381
  case "==":
2351
- return `eq ${left} ${right}`;
2382
+ result = `eq ${left} ${right}`;
2383
+ break;
2352
2384
  case "!==":
2353
2385
  case "!=":
2354
- return `ne ${left} ${right}`;
2386
+ result = `ne ${left} ${right}`;
2387
+ break;
2355
2388
  case ">":
2356
- return `gt ${left} ${right}`;
2389
+ result = `gt ${left} ${right}`;
2390
+ break;
2357
2391
  case "<":
2358
- return `lt ${left} ${right}`;
2392
+ result = `lt ${left} ${right}`;
2393
+ break;
2359
2394
  case ">=":
2360
- return `ge ${left} ${right}`;
2395
+ result = `ge ${left} ${right}`;
2396
+ break;
2361
2397
  case "<=":
2362
- return `le ${left} ${right}`;
2398
+ result = `le ${left} ${right}`;
2399
+ break;
2363
2400
  case "+":
2364
- return `bf_add ${left} ${right}`;
2401
+ result = `bf_add ${left} ${right}`;
2402
+ break;
2365
2403
  case "-":
2366
- return `bf_sub ${left} ${right}`;
2404
+ result = `bf_sub ${left} ${right}`;
2405
+ break;
2367
2406
  case "*":
2368
- return `bf_mul ${left} ${right}`;
2407
+ result = `bf_mul ${left} ${right}`;
2408
+ break;
2369
2409
  case "/":
2370
- return `bf_div ${left} ${right}`;
2410
+ result = `bf_div ${left} ${right}`;
2411
+ break;
2371
2412
  default:
2372
- return `${left} ${expr.op} ${right}`;
2413
+ result = `${left} ${expr.op} ${right}`;
2373
2414
  }
2415
+ return { preamble, expr: result };
2374
2416
  }
2375
2417
  case "unary": {
2376
2418
  const arg = this.renderConditionExpr(expr.argument);
2377
- if (expr.op === "!") {
2378
- return `not ${arg}`;
2379
- }
2380
- if (expr.op === "-") {
2381
- return `bf_neg ${arg}`;
2382
- }
2419
+ if (expr.op === "!")
2420
+ return { preamble: arg.preamble, expr: `not ${arg.expr}` };
2421
+ if (expr.op === "-")
2422
+ return { preamble: arg.preamble, expr: `bf_neg ${arg.expr}` };
2383
2423
  return arg;
2384
2424
  }
2385
2425
  case "logical": {
2386
- const left = this.renderConditionExpr(expr.left);
2387
- const right = this.renderConditionExpr(expr.right);
2388
- const wrapLeft = this.needsParens(expr.left) ? `(${left})` : left;
2389
- const wrapRight = this.needsParens(expr.right) ? `(${right})` : right;
2390
- if (expr.op === "&&") {
2391
- return `and ${wrapLeft} ${wrapRight}`;
2392
- }
2393
- return `or ${wrapLeft} ${wrapRight}`;
2426
+ const leftResult = this.renderConditionExpr(expr.left);
2427
+ const rightResult = this.renderConditionExpr(expr.right);
2428
+ const preamble = leftResult.preamble + rightResult.preamble;
2429
+ const wrapLeft = this.needsParens(expr.left) ? `(${leftResult.expr})` : leftResult.expr;
2430
+ const wrapRight = this.needsParens(expr.right) ? `(${rightResult.expr})` : rightResult.expr;
2431
+ const result = expr.op === "&&" ? `and ${wrapLeft} ${wrapRight}` : `or ${wrapLeft} ${wrapRight}`;
2432
+ return { preamble, expr: result };
2394
2433
  }
2395
2434
  case "conditional": {
2396
2435
  const test = this.renderConditionExpr(expr.test);
2397
2436
  return test;
2398
2437
  }
2399
2438
  case "template-literal":
2400
- return this.renderParsedExpr(expr);
2439
+ return plain(this.renderParsedExpr(expr));
2401
2440
  case "arrow-fn":
2402
- return "[ARROW-FN]";
2403
- case "higher-order":
2404
- return this.renderParsedExpr(expr);
2441
+ return plain("[ARROW-FN]");
2442
+ case "higher-order": {
2443
+ const rendered = this.renderParsedExpr(expr);
2444
+ const split = this.splitPreamble(rendered);
2445
+ if (split)
2446
+ return split;
2447
+ return plain(rendered);
2448
+ }
2405
2449
  case "array-literal":
2406
- return this.renderParsedExpr(expr);
2450
+ return plain(this.renderParsedExpr(expr));
2407
2451
  case "array-method":
2408
- return this.renderParsedExpr(expr);
2452
+ return plain(this.renderParsedExpr(expr));
2409
2453
  case "unsupported":
2410
- return expr.raw;
2454
+ return plain(expr.raw);
2411
2455
  }
2412
2456
  }
2413
2457
  renderLoop(loop) {
@@ -2430,14 +2474,38 @@ Options:
2430
2474
  }
2431
2475
  let goArray = this.convertExpressionToGo(loop.array);
2432
2476
  const param = loop.param;
2433
- const index = loop.index || "_";
2477
+ let index = loop.index || "_";
2478
+ let rangeIndex = index;
2479
+ let rangeValue = param;
2480
+ if (loop.iterationShape === "keys") {
2481
+ rangeIndex = param;
2482
+ rangeValue = "_";
2483
+ }
2434
2484
  const childComponent = this.findChildComponent(loop.children);
2435
2485
  if (childComponent) {
2436
2486
  goArray = `.${childComponent.name}s`;
2437
2487
  }
2438
2488
  this.inLoop = true;
2439
- this.loopParamStack.push(param);
2489
+ const addedLoopVars = [];
2490
+ if (loop.iterationShape === "keys") {
2491
+ this.loopParamStack.push("");
2492
+ this.loopVarRefCount.set(param, (this.loopVarRefCount.get(param) ?? 0) + 1);
2493
+ addedLoopVars.push(param);
2494
+ } else {
2495
+ this.loopParamStack.push(param);
2496
+ if (rangeIndex !== "_") {
2497
+ this.loopVarRefCount.set(rangeIndex, (this.loopVarRefCount.get(rangeIndex) ?? 0) + 1);
2498
+ addedLoopVars.push(rangeIndex);
2499
+ }
2500
+ }
2440
2501
  const children = this.renderChildren(loop.children);
2502
+ for (const v of addedLoopVars) {
2503
+ const rc = (this.loopVarRefCount.get(v) ?? 1) - 1;
2504
+ if (rc <= 0)
2505
+ this.loopVarRefCount.delete(v);
2506
+ else
2507
+ this.loopVarRefCount.set(v, rc);
2508
+ }
2441
2509
  this.loopParamStack.pop();
2442
2510
  this.inLoop = false;
2443
2511
  if (loop.sortComparator) {
@@ -2453,10 +2521,10 @@ Options:
2453
2521
  filterCond = "true";
2454
2522
  }
2455
2523
  const itemMarker2 = loop.bodyIsMultiRoot ? `{{bfComment "bf-loop-i"}}` : "";
2456
- return `{{bfComment "loop:${loop.markerId}"}}{{range $${index}, $${param} := ${goArray}}}{{if ${filterCond}}}${itemMarker2}${children}{{end}}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
2524
+ return `{{bfComment "loop:${loop.markerId}"}}{{range $${rangeIndex}, $${rangeValue} := ${goArray}}}{{if ${filterCond}}}${itemMarker2}${children}{{end}}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
2457
2525
  }
2458
2526
  const itemMarker = loop.bodyIsMultiRoot ? `{{bfComment "bf-loop-i"}}` : "";
2459
- return `{{bfComment "loop:${loop.markerId}"}}{{range $${index}, $${param} := ${goArray}}}${itemMarker}${children}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
2527
+ return `{{bfComment "loop:${loop.markerId}"}}{{range $${rangeIndex}, $${rangeValue} := ${goArray}}}${itemMarker}${children}{{end}}{{bfComment "/loop:${loop.markerId}"}}`;
2460
2528
  }
2461
2529
  findChildComponent(nodes) {
2462
2530
  for (const node of nodes) {