inscript-lang 1.9.7__tar.gz → 1.9.8__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-1.9.7 → inscript_lang-1.9.8}/PKG-INFO +1 -1
  2. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/analyzer.py +12 -4
  3. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript.py +80 -1
  4. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_lang.egg-info/PKG-INFO +1 -1
  5. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/pyproject.toml +1 -1
  6. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/repl.py +1 -1
  7. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/README.md +0 -0
  8. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/ast_nodes.py +0 -0
  9. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/compiler.py +0 -0
  10. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/environment.py +0 -0
  11. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/errors.py +0 -0
  12. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_fmt.py +0 -0
  13. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_lang.egg-info/SOURCES.txt +0 -0
  14. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_lang.egg-info/dependency_links.txt +0 -0
  15. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_lang.egg-info/entry_points.txt +0 -0
  16. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_lang.egg-info/requires.txt +0 -0
  17. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_lang.egg-info/top_level.txt +0 -0
  18. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/inscript_test.py +0 -0
  19. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/interpreter.py +0 -0
  20. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/lexer.py +0 -0
  21. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/parser.py +0 -0
  22. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/pygame_backend.py +0 -0
  23. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/setup.cfg +0 -0
  24. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/setup.py +0 -0
  25. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/stdlib.py +0 -0
  26. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/stdlib_extended.py +0 -0
  27. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/stdlib_extended_2.py +0 -0
  28. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/stdlib_game.py +0 -0
  29. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/stdlib_values.py +0 -0
  30. {inscript_lang-1.9.7 → inscript_lang-1.9.8}/vm.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: inscript-lang
3
- Version: 1.9.7
3
+ Version: 1.9.8
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
@@ -1151,13 +1151,21 @@ class Analyzer(Visitor):
1151
1151
  def visit_ArrayLiteralExpr(self, node: ArrayLiteralExpr) -> InScriptType:
1152
1152
  if not node.elements:
1153
1153
  return array_type(T_ANY)
1154
+ # v1.9.8: infer element type; fall back to Array<any> on mixed types
1154
1155
  first_type = self.visit(node.elements[0])
1156
+ # Normalise literal string types to T_STRING for array inference
1157
+ if is_literal_type(first_type):
1158
+ first_type = T_STRING
1159
+ mixed = False
1155
1160
  for elem in node.elements[1:]:
1156
1161
  et = self.visit(elem)
1157
- if not types_compatible(first_type, et):
1158
- self._warn(f"Mixed types in array literal: '{first_type}' and '{et}'",
1159
- node.line)
1160
- return array_type(first_type)
1162
+ if is_literal_type(et):
1163
+ et = T_STRING
1164
+ if not types_compatible(first_type, et) and not types_compatible(et, first_type):
1165
+ mixed = True
1166
+ if mixed:
1167
+ return array_type(T_ANY) # [1, "a", true] → Array<any>
1168
+ return array_type(first_type) # [1, 2, 3] → Array<int>
1161
1169
 
1162
1170
  def visit_DictLiteralExpr(self, node: DictLiteralExpr) -> InScriptType:
1163
1171
  if not node.pairs:
@@ -24,7 +24,7 @@ from errors import (InScriptError, LexerError, ParseError,
24
24
  SemanticError, InScriptRuntimeError,
25
25
  MultiError, InScriptWarning)
26
26
 
27
- VERSION = "1.9.7"
27
+ VERSION = "1.9.8"
28
28
  LANG = "InScript"
29
29
  PACKAGES_DIR = os.path.join(os.path.expanduser("~"), ".inscript", "packages")
30
30
  REGISTRY_URL = "https://raw.githubusercontent.com/authorss81/inscript-packages/main/registry.json"
@@ -315,6 +315,81 @@ def _compat_files(path: str) -> int:
315
315
  return 1
316
316
 
317
317
 
318
+ def _infer_types_file(path: str) -> int:
319
+ """
320
+ v1.9.8: `inscript --infer-types FILE`
321
+ Parse and type-check FILE, then print the inferred type for every
322
+ let/const declaration. Useful for understanding what the analyzer infers.
323
+ Returns 0 on success, 1 if file not found or parse error.
324
+ """
325
+ import os
326
+ if not os.path.isfile(path):
327
+ print(f"[InScript infer-types] File not found: '{path}'", file=sys.stderr)
328
+ return 1
329
+ try:
330
+ with open(path, encoding="utf-8") as f:
331
+ src = f.read()
332
+ except OSError as e:
333
+ print(f"[InScript infer-types] Cannot read '{path}': {e}", file=sys.stderr)
334
+ return 1
335
+
336
+ from lexer import Lexer
337
+ from parser import Parser
338
+ from analyzer import Analyzer
339
+ from ast_nodes import VarDecl
340
+
341
+ try:
342
+ tokens = Lexer(src).tokenize()
343
+ tree = Parser(tokens).parse()
344
+ except Exception as e:
345
+ print(f"[InScript infer-types] Parse error: {e}", file=sys.stderr)
346
+ return 1
347
+
348
+ analyzer = Analyzer()
349
+ try:
350
+ analyzer.analyze(tree)
351
+ except Exception:
352
+ pass # best-effort — show what we have even if there are errors
353
+
354
+ # Walk all VarDecl / ConstDecl nodes and report inferred types
355
+ results = []
356
+ def _walk(node):
357
+ if node is None:
358
+ return
359
+ if isinstance(node, (VarDecl,)):
360
+ sym = analyzer._scope.lookup(node.name) if hasattr(analyzer, '_scope') else None
361
+ typ = sym.type_ if sym else None
362
+ type_str = str(typ) if typ else "any"
363
+ results.append((node.line, "let" if not node.is_const else "const",
364
+ node.name, type_str))
365
+ # Recurse into body of blocks, fns etc.
366
+ for attr in ("body", "then_branch", "else_branch", "value",
367
+ "initializer", "statements"):
368
+ child = getattr(node, attr, None)
369
+ if child is None:
370
+ continue
371
+ if hasattr(child, "__iter__") and not isinstance(child, str):
372
+ for c in child:
373
+ if hasattr(c, "__class__") and hasattr(c, "line"):
374
+ _walk(c)
375
+ elif hasattr(child, "line"):
376
+ _walk(child)
377
+
378
+ if hasattr(tree, "body"):
379
+ for stmt in tree.body:
380
+ _walk(stmt)
381
+
382
+ if not results:
383
+ print(f"[InScript infer-types] No let/const declarations found in '{path}'")
384
+ return 0
385
+
386
+ print(f"[InScript infer-types] Inferred types in '{path}':\n")
387
+ for line, kw, name, typ in results:
388
+ print(f" Line {line:3d}: {kw} {name:<20s} → {typ}")
389
+ print()
390
+ return 0
391
+
392
+
318
393
  def _migrate_files(path: str) -> int:
319
394
  """v1.7.4: Auto-migrate deprecated InScript syntax in-place."""
320
395
  import re, os
@@ -1573,6 +1648,8 @@ Examples:
1573
1648
  parser.add_argument("--check", action="store_true", help="Type-check only, don't run")
1574
1649
  parser.add_argument("--check-all", metavar="DIR",
1575
1650
  help="v1.6.0: Check all .ins files in DIR recursively, exit 1 if any errors")
1651
+ parser.add_argument("--infer-types", metavar="FILE",
1652
+ help="v1.9.8: Print inferred type for every let/const declaration in FILE")
1576
1653
  parser.add_argument("--migrate", metavar="DIR_OR_FILE",
1577
1654
  help="v1.7.4: Auto-migrate deprecated syntax (null→nil, div→//)")
1578
1655
  parser.add_argument("--compat", metavar="DIR_OR_FILE",
@@ -1754,6 +1831,8 @@ Examples:
1754
1831
  return _fmt_all_files(args.fmt_all)
1755
1832
  if getattr(args, 'migrate', None):
1756
1833
  return _migrate_files(args.migrate)
1834
+ if getattr(args, 'infer_types', None):
1835
+ return _infer_types_file(args.infer_types)
1757
1836
  if getattr(args, 'compat', None):
1758
1837
  return _compat_files(args.compat)
1759
1838
  if getattr(args, 'init', None) is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: inscript-lang
3
- Version: 1.9.7
3
+ Version: 1.9.8
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "inscript-lang"
7
- version = "1.9.7"
7
+ version = "1.9.8"
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 = "1.9.7"
43
+ VERSION = "1.9.8"
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