inscript-lang 2.0.1__tar.gz → 2.0.2__tar.gz

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.
Files changed (30) hide show
  1. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/PKG-INFO +1 -1
  2. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript.py +1 -1
  3. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_lang.egg-info/PKG-INFO +1 -1
  4. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/interpreter.py +65 -36
  5. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/pyproject.toml +1 -1
  6. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/repl.py +1 -1
  7. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/README.md +0 -0
  8. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/analyzer.py +0 -0
  9. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/ast_nodes.py +0 -0
  10. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/compiler.py +0 -0
  11. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/environment.py +0 -0
  12. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/errors.py +0 -0
  13. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_fmt.py +0 -0
  14. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_lang.egg-info/SOURCES.txt +0 -0
  15. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_lang.egg-info/dependency_links.txt +0 -0
  16. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_lang.egg-info/entry_points.txt +0 -0
  17. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_lang.egg-info/requires.txt +0 -0
  18. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_lang.egg-info/top_level.txt +0 -0
  19. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/inscript_test.py +0 -0
  20. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/lexer.py +0 -0
  21. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/parser.py +0 -0
  22. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/pygame_backend.py +0 -0
  23. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/setup.cfg +0 -0
  24. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/setup.py +0 -0
  25. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/stdlib.py +0 -0
  26. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/stdlib_extended.py +0 -0
  27. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/stdlib_extended_2.py +0 -0
  28. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/stdlib_game.py +0 -0
  29. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/stdlib_values.py +0 -0
  30. {inscript_lang-2.0.1 → inscript_lang-2.0.2}/vm.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: inscript-lang
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: InScript — a game-focused scripting language with 59 game modules and a bytecode VM
5
5
  Author: Shreyasi Sarkar
6
6
  License: MIT
@@ -24,7 +24,7 @@ from errors import (InScriptError, LexerError, ParseError,
24
24
  SemanticError, InScriptRuntimeError,
25
25
  MultiError, InScriptWarning)
26
26
 
27
- VERSION = "2.0.1"
27
+ VERSION = "2.0.2"
28
28
 
29
29
  MANIFEST_FILENAME = "inscript.toml"
30
30
  LOCK_FILENAME = "inscript.lock"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: inscript-lang
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: InScript — a game-focused scripting language with 59 game modules and a bytecode VM
5
5
  Author: Shreyasi Sarkar
6
6
  License: MIT
@@ -2516,41 +2516,76 @@ class Interpreter(Visitor):
2516
2516
  cond = self.visit(node.condition)
2517
2517
  return self.visit(node.then_expr) if cond else self.visit(node.else_expr)
2518
2518
 
2519
+ @staticmethod
2520
+ def _fstring_segments(template: str):
2521
+ """v2.0.2: brace-depth-aware f-string segment splitter.
2522
+ Returns list of (kind, text) where kind is "lit" or "expr".
2523
+ Handles nested braces (match, for, object literals) correctly.
2524
+ {{ and }} in source are stored as sentinel \x00{ and }\x00.
2525
+ """
2526
+ segments = []
2527
+ i = 0
2528
+ n = len(template)
2529
+ lit_buf = []
2530
+ while i < n:
2531
+ ch = template[i]
2532
+ # Sentinel escaped braces: \x00{ = literal {, }\x00 = literal }
2533
+ if ch == "\x00" and i + 1 < n and template[i + 1] == "{":
2534
+ lit_buf.append("{"); i += 2
2535
+ elif ch == "}" and i + 1 < n and template[i + 1] == "\x00":
2536
+ lit_buf.append("}"); i += 2
2537
+ elif ch == "{":
2538
+ # Start of an expression — find matching } with depth tracking
2539
+ if lit_buf:
2540
+ segments.append(("lit", "".join(lit_buf))); lit_buf = []
2541
+ depth = 1; j = i + 1; in_str = None
2542
+ while j < n and depth > 0:
2543
+ c2 = template[j]
2544
+ if in_str:
2545
+ if c2 == "\\" and j + 1 < n: j += 2; continue
2546
+ if c2 == in_str: in_str = None
2547
+ elif c2 in ('"', "\'"):
2548
+ in_str = c2
2549
+ elif c2 == "{":
2550
+ depth += 1
2551
+ elif c2 == "}":
2552
+ depth -= 1
2553
+ if depth == 0: break
2554
+ j += 1
2555
+ segments.append(("expr", template[i + 1:j]))
2556
+ i = j + 1
2557
+ else:
2558
+ lit_buf.append(ch); i += 1
2559
+ if lit_buf:
2560
+ segments.append(("lit", "".join(lit_buf)))
2561
+ return segments
2562
+
2519
2563
  def visit_FStringExpr(self, node: FStringExpr) -> Any:
2520
2564
  """f"Hello {name}, score={score:.1f}" — evaluate {expr} segments at runtime.
2565
+ v2.0.2: brace-depth-aware splitter handles match/for/object literals inside {}.
2521
2566
  Supports Python-style format specs: {x:.2f}, {n:06d}, {s:>20} etc.
2522
- {{ and }} in source produce literal braces (stored as \x00{ and }\x00 sentinels)."""
2523
- import re
2567
+ {{ and }} in source produce literal braces."""
2524
2568
  result = []
2525
- template = node.template
2526
- pos = 0
2527
- for m in re.finditer(r'(?<!\x00)\{([^}\x00][^}]*)\}', template):
2528
- result.append(template[pos:m.start()])
2529
- inner = m.group(1).strip()
2530
-
2531
- # Split off format spec: {expr:spec}
2532
- # Key: only split on ':' that is NOT inside brackets AND NOT after '?'
2533
- # (ternary x ? a : b uses ':' but it's not a format spec)
2569
+ for kind, text in self._fstring_segments(node.template):
2570
+ if kind == "lit":
2571
+ result.append(text)
2572
+ continue
2573
+ inner = text.strip()
2574
+ # Split off format spec {expr:spec}, respecting brackets and ternary
2534
2575
  fmt_spec = None
2535
- depth = 0
2536
- ternary_depth = 0
2537
- split_at = -1
2576
+ depth = 0; ternary_depth = 0; split_at = -1
2538
2577
  for i, ch in enumerate(inner):
2539
- if ch in '([{': depth += 1
2540
- elif ch in ')]}': depth -= 1
2541
- elif ch == '?' and depth == 0: ternary_depth += 1
2542
- elif ch == ':' and depth == 0:
2543
- if ternary_depth > 0:
2544
- ternary_depth -= 1 # this ':' closes the ternary
2545
- else:
2546
- split_at = i
2547
- break
2578
+ if ch in "([{": depth += 1
2579
+ elif ch in ")]}": depth -= 1
2580
+ elif ch == "?" and depth == 0: ternary_depth += 1
2581
+ elif ch == ":" and depth == 0:
2582
+ if ternary_depth > 0: ternary_depth -= 1
2583
+ else: split_at = i; break
2548
2584
  if split_at > 0:
2549
- expr_src = inner[:split_at].strip()
2550
- fmt_spec = inner[split_at+1:].strip()
2585
+ expr_src = inner[:split_at].strip()
2586
+ fmt_spec = inner[split_at + 1:].strip()
2551
2587
  else:
2552
2588
  expr_src = inner
2553
-
2554
2589
  try:
2555
2590
  from parser import parse
2556
2591
  prog = parse(expr_src)
@@ -2558,19 +2593,13 @@ class Interpreter(Visitor):
2558
2593
  for stmt in prog.body:
2559
2594
  val = self.visit(stmt)
2560
2595
  if fmt_spec:
2561
- # Apply Python format spec directly — supports .2f, 06d, >10s etc.
2562
- try:
2563
- result.append(format(val, fmt_spec))
2564
- except Exception:
2565
- result.append(_inscript_str(val))
2596
+ try: result.append(format(val, fmt_spec))
2597
+ except: result.append(_inscript_str(val))
2566
2598
  else:
2567
2599
  result.append(_inscript_str(val))
2568
2600
  except Exception:
2569
- result.append(f"{{{inner}}}")
2570
- pos = m.end()
2571
- result.append(template[pos:])
2572
- final = "".join(result).replace("\x00{", "{").replace("}\x00", "}")
2573
- return final
2601
+ result.append("{" + inner + "}")
2602
+ return "".join(result)
2574
2603
 
2575
2604
  def visit_DestructureDecl(self, node: DestructureDecl) -> Any:
2576
2605
  """let [a, b, c] = arr | let {x, y} = point | let [[a,b],[c,d]] = nested"""
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "inscript-lang"
7
- version = "2.0.1"
7
+ version = "2.0.2"
8
8
  description = "InScript — a game-focused scripting language with 59 game modules and a bytecode VM"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -40,7 +40,7 @@ sys.path.insert(0, str(Path(__file__).parent))
40
40
 
41
41
  HISTORY_FILE = Path.home() / ".inscript" / "history"
42
42
  HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True)
43
- VERSION = "2.0.1"
43
+ VERSION = "2.0.2"
44
44
 
45
45
  # ── ANSI colours ──────────────────────────────────────────────────────────────
46
46
  def _c(code, text):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes