tova 0.9.6 → 0.9.8

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/bin/tova.js CHANGED
@@ -4541,6 +4541,35 @@ async function startRepl() {
4541
4541
  context.__mutable.add(m[1]);
4542
4542
  }
4543
4543
 
4544
+ // Fix REPL reassignment: when compiled code declares variables that
4545
+ // already exist in context, convert to reassignment to avoid TDZ errors.
4546
+ // e.g., "a, b = b, a" compiles to "const [a, b] = [b, a];" but b/a on
4547
+ // the RHS are in TDZ because they're excluded from context destructure.
4548
+ let replCode = code;
4549
+ // Array/tuple destructuring: const [a, b] = [...] → [a, b] = [...]
4550
+ replCode = replCode.replace(/^(const|let)\s+(\[[^\]]+\])\s*=/gm, (match, kw, targets) => {
4551
+ const names = targets.slice(1, -1).split(',').map(n => n.trim()).filter(Boolean);
4552
+ if (names.length > 0 && names.every(n => n in context)) {
4553
+ for (const n of names) {
4554
+ declaredInCode.delete(n);
4555
+ if (!context.__mutable) context.__mutable = new Set();
4556
+ context.__mutable.add(n);
4557
+ }
4558
+ return `${targets} =`;
4559
+ }
4560
+ return match;
4561
+ });
4562
+ // Single variable: const x = expr → x = expr (when x exists in context)
4563
+ replCode = replCode.replace(/^(const|let)\s+([a-zA-Z_]\w*)\s*=/gm, (match, kw, name) => {
4564
+ if (name in context) {
4565
+ declaredInCode.delete(name);
4566
+ if (!context.__mutable) context.__mutable = new Set();
4567
+ context.__mutable.add(name);
4568
+ return `${name} =`;
4569
+ }
4570
+ return match;
4571
+ });
4572
+
4544
4573
  // Save declared variables back to context for persistence across inputs
4545
4574
  const saveNewDecls = declaredInCode.size > 0
4546
4575
  ? [...declaredInCode].map(n => `if(typeof ${n}!=='undefined')__ctx.${n}=${n};`).join('\n')
@@ -4561,17 +4590,17 @@ async function startRepl() {
4561
4590
  (letKeys.length > 0 ? `let {${letKeys.join(',')}} = __ctx;\n` : '');
4562
4591
 
4563
4592
  // Try wrapping last expression statement as a return for value display
4564
- const lines = code.trim().split('\n');
4593
+ const lines = replCode.trim().split('\n');
4565
4594
  const lastLine = lines[lines.length - 1].trim();
4566
- let evalCode = code;
4595
+ let evalCode = replCode;
4567
4596
  // For simple assignments (const x = expr;), echo the assigned value
4568
4597
  const constAssignMatch = lastLine.match(/^(const|let)\s+([a-zA-Z_]\w*)\s*=\s*(.+);?$/);
4569
4598
  if (constAssignMatch) {
4570
4599
  const varName = constAssignMatch[2];
4571
4600
  if (allSave) {
4572
- evalCode = `${code}\n${allSave}\nreturn ${varName};`;
4601
+ evalCode = `${replCode}\n${allSave}\nreturn ${varName};`;
4573
4602
  } else {
4574
- evalCode = `${code}\nreturn ${varName};`;
4603
+ evalCode = `${replCode}\nreturn ${varName};`;
4575
4604
  }
4576
4605
  } else if (!/^(const |let |var |function |if |for |while |class |try |switch )/.test(lastLine) && !lastLine.endsWith('{')) {
4577
4606
  // Replace the last statement with a return
@@ -4585,7 +4614,7 @@ async function startRepl() {
4585
4614
  evalCode = allButLast + (allButLast ? '\n' : '') + `return (${returnExpr});`;
4586
4615
  }
4587
4616
  } else {
4588
- evalCode = code + (allSave ? '\n' + allSave : '');
4617
+ evalCode = replCode + (allSave ? '\n' + allSave : '');
4589
4618
  }
4590
4619
  try {
4591
4620
  const fn = new Function('__ctx', `${destructure}${evalCode}`);
@@ -4597,7 +4626,7 @@ async function startRepl() {
4597
4626
  }
4598
4627
  } catch (e) {
4599
4628
  // If return-wrapping fails, fall back to plain execution
4600
- const fallbackCode = code + (allSave ? '\n' + allSave : '');
4629
+ const fallbackCode = replCode + (allSave ? '\n' + allSave : '');
4601
4630
  const fn = new Function('__ctx', `${destructure}${fallbackCode}`);
4602
4631
  fn(context);
4603
4632
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tova",
3
- "version": "0.9.6",
3
+ "version": "0.9.8",
4
4
  "description": "Tova — a modern programming language that transpiles to JavaScript, unifying frontend and backend",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -2328,7 +2328,8 @@ export class BaseCodegen {
2328
2328
  }
2329
2329
 
2330
2330
  // window() / table_window() — partition_by/order_by/desc are meta, rest are window fns
2331
- if (calleeName === 'window' || calleeName === 'table_window') {
2331
+ // Only apply named-argument rewriting when actual NamedArguments are used
2332
+ if ((calleeName === 'window' || calleeName === 'table_window') && node.arguments.some(a => a.type === 'NamedArgument')) {
2332
2333
  const META_KEYS = new Set(['partition_by', 'order_by', 'desc']);
2333
2334
  const optParts = [];
2334
2335
  const winParts = [];
@@ -1651,6 +1651,14 @@ export const STDLIB_DEPS = {
1651
1651
  json_parse: ['Ok', 'Err'],
1652
1652
  date_parse: ['Ok', 'Err'],
1653
1653
  read_text: ['Ok', 'Err'],
1654
+ read_bytes: ['Ok', 'Err'],
1655
+ write_text: ['Ok', 'Err'],
1656
+ mkdir: ['Ok', 'Err'],
1657
+ rm: ['Ok', 'Err'],
1658
+ cp: ['Ok', 'Err'],
1659
+ mv: ['Ok', 'Err'],
1660
+ file_stat: ['Ok', 'Err'],
1661
+ file_size: ['Ok', 'Err'],
1654
1662
  try_fn: ['Ok', 'Err'],
1655
1663
  try_async: ['Ok', 'Err'],
1656
1664
  // LazyTable requires Table and table_* functions
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by scripts/embed-runtime.js — do not edit
2
- export const VERSION = "0.9.6";
2
+ export const VERSION = "0.9.8";