inscript-lang 3.0.0__tar.gz → 3.9.6.23__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 (54) hide show
  1. inscript_lang-3.9.6.23/PKG-INFO +148 -0
  2. inscript_lang-3.9.6.23/README.md +115 -0
  3. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/analyzer.py +25 -0
  4. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/compiler.py +67 -0
  5. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript.py +59 -7
  6. inscript_lang-3.9.6.23/inscript_lang.egg-info/PKG-INFO +148 -0
  7. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/SOURCES.txt +13 -1
  8. inscript_lang-3.9.6.23/inscript_lang.egg-info/not-zip-safe +1 -0
  9. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/top_level.txt +2 -0
  10. inscript_lang-3.9.6.23/inscript_rust_parser/Cargo.toml +17 -0
  11. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/interpreter.py +211 -10
  12. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/lexer.py +196 -9
  13. inscript_lang-3.9.6.23/lsp/__init__.py +6 -0
  14. inscript_lang-3.9.6.23/lsp/code_actions.py +95 -0
  15. inscript_lang-3.9.6.23/lsp/completions.py +189 -0
  16. inscript_lang-3.9.6.23/lsp/definition.py +144 -0
  17. inscript_lang-3.9.6.23/lsp/diagnostics.py +58 -0
  18. inscript_lang-3.9.6.23/lsp/hover.py +128 -0
  19. inscript_lang-3.9.6.23/lsp/semantic_tokens.py +134 -0
  20. inscript_lang-3.9.6.23/lsp/server.py +346 -0
  21. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/parser.py +9 -4
  22. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/pygame_backend.py +382 -19
  23. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/pyproject.toml +4 -1
  24. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/repl.py +1 -1
  25. inscript_lang-3.9.6.23/setup.py +126 -0
  26. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib.py +7 -0
  27. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_assets.py +6 -1
  28. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_game.py +111 -3
  29. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/studio_bridge.py +72 -2
  30. inscript_lang-3.9.6.23/tools/__init__.py +0 -0
  31. inscript_lang-3.9.6.23/tools/sync_versions.py +80 -0
  32. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/vm.py +50 -4
  33. inscript_lang-3.0.0/PKG-INFO +0 -210
  34. inscript_lang-3.0.0/README.md +0 -179
  35. inscript_lang-3.0.0/inscript_lang.egg-info/PKG-INFO +0 -210
  36. inscript_lang-3.0.0/setup.py +0 -75
  37. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/ast_nodes.py +0 -0
  38. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/environment.py +0 -0
  39. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/errors.py +0 -0
  40. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/export_pipeline.py +0 -0
  41. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/hot_reload.py +0 -0
  42. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_dap.py +0 -0
  43. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_fmt.py +0 -0
  44. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/dependency_links.txt +0 -0
  45. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/entry_points.txt +0 -0
  46. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/requires.txt +0 -0
  47. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_studio_api.py +0 -0
  48. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_test.py +0 -0
  49. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/scene_tree.py +0 -0
  50. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/setup.cfg +0 -0
  51. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_extended.py +0 -0
  52. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_extended_2.py +0 -0
  53. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_values.py +0 -0
  54. {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/studio_readiness.py +0 -0
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: inscript-lang
3
+ Version: 3.9.6.23
4
+ Summary: InScript — a game-focused scripting language with 59 game modules and a bytecode VM
5
+ Home-page: https://github.com/authorss81/inscript
6
+ Author: Shreyasi Sarkar
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/authorss81/inscript
9
+ Project-URL: Repository, https://github.com/authorss81/inscript
10
+ Project-URL: Bug Tracker, https://github.com/authorss81/inscript/issues
11
+ Project-URL: Documentation, https://authorss81.github.io/inscript/docs/
12
+ Keywords: game,scripting,language,gamedev,gdscript
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Games/Entertainment
21
+ Classifier: Topic :: Software Development :: Interpreters
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ Provides-Extra: game
25
+ Requires-Dist: pygame>=2.0; extra == "game"
26
+ Provides-Extra: lsp
27
+ Requires-Dist: pygls>=1.0; extra == "lsp"
28
+ Provides-Extra: all
29
+ Requires-Dist: pygame>=2.0; extra == "all"
30
+ Requires-Dist: pygls>=1.0; extra == "all"
31
+ Dynamic: home-page
32
+ Dynamic: requires-python
33
+
34
+ # InScript Lexer - Rust Implementation (v3.7.2)
35
+
36
+ **Real, compilable Rust tokenizer** for InScript language.
37
+
38
+ ## Features
39
+
40
+ ✅ Zero-copy token references (fast, memory efficient)
41
+ ✅ State machine lexer (no backtracking)
42
+ ✅ 30+ token types (keywords, operators, literals)
43
+ ✅ Accurate line/column tracking
44
+ ✅ Comprehensive error reporting
45
+ ✅ Python FFI via PyO3
46
+ ✅ Full test coverage
47
+
48
+ ## Build
49
+
50
+ ```bash
51
+ cargo build --release
52
+ ```
53
+
54
+ ## Token Types Supported
55
+
56
+ ### Literals
57
+ - Numbers (integers and floats)
58
+ - Strings (single and double quoted)
59
+ - Identifiers
60
+
61
+ ### Keywords
62
+ - if, else, while, for, fn, return
63
+ - true, false, nil
64
+ - and, or, not
65
+
66
+ ### Operators
67
+ - Arithmetic: +, -, *, /, %
68
+ - Comparison: ==, !=, <, <=, >, >=
69
+ - Assignment: =
70
+ - Logical: and, or, not
71
+
72
+ ### Delimiters
73
+ - Parentheses: ( )
74
+ - Braces: { }
75
+ - Brackets: [ ]
76
+ - Punctuation: , . ; : ->
77
+
78
+ ## Rust Usage
79
+
80
+ ```rust
81
+ use inscript_lexer::Lexer;
82
+
83
+ fn main() {
84
+ let code = "let x = 42;";
85
+ let lexer = Lexer::new(code);
86
+
87
+ for token in lexer {
88
+ match token {
89
+ Ok(t) => println!("{:?}: {}", t.token_type, t.value),
90
+ Err(e) => eprintln!("Error: {}", e),
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Python Usage (after compilation)
97
+
98
+ ```python
99
+ from inscript_lexer import PyLexer, tokenize_string
100
+
101
+ # Method 1: Using PyLexer class
102
+ lexer = PyLexer("let x = 42;")
103
+ tokens = lexer.tokens()
104
+ print(f"Found {lexer.count()} tokens")
105
+
106
+ # Method 2: Direct tokenization
107
+ tokens = tokenize_string("if true then x else y")
108
+ for token in tokens:
109
+ print(f"{token.token_type}: {token.value}")
110
+ ```
111
+
112
+ ## Performance
113
+
114
+ ### Expected Benchmarks
115
+ - Simple tokens: < 100ns per token
116
+ - Complex code: < 10µs per 100 tokens
117
+ - Memory: O(1) per token
118
+
119
+ ### Optimizations
120
+ - Inline hot paths
121
+ - No allocations in common cases
122
+ - SIMD-friendly string scanning
123
+ - Zero-copy string references
124
+
125
+ ## Testing
126
+
127
+ ```bash
128
+ # Run tests
129
+ cargo test
130
+
131
+ # Run with output
132
+ cargo test -- --nocapture
133
+
134
+ # Benchmark
135
+ cargo bench
136
+ ```
137
+
138
+ ## Accuracy
139
+
140
+ ✅ Correct line/column tracking
141
+ ✅ Handles escape sequences
142
+ ✅ Detects unterminated strings
143
+ ✅ Error recovery
144
+
145
+ ## License
146
+
147
+ MIT
148
+
@@ -0,0 +1,115 @@
1
+ # InScript Lexer - Rust Implementation (v3.7.2)
2
+
3
+ **Real, compilable Rust tokenizer** for InScript language.
4
+
5
+ ## Features
6
+
7
+ ✅ Zero-copy token references (fast, memory efficient)
8
+ ✅ State machine lexer (no backtracking)
9
+ ✅ 30+ token types (keywords, operators, literals)
10
+ ✅ Accurate line/column tracking
11
+ ✅ Comprehensive error reporting
12
+ ✅ Python FFI via PyO3
13
+ ✅ Full test coverage
14
+
15
+ ## Build
16
+
17
+ ```bash
18
+ cargo build --release
19
+ ```
20
+
21
+ ## Token Types Supported
22
+
23
+ ### Literals
24
+ - Numbers (integers and floats)
25
+ - Strings (single and double quoted)
26
+ - Identifiers
27
+
28
+ ### Keywords
29
+ - if, else, while, for, fn, return
30
+ - true, false, nil
31
+ - and, or, not
32
+
33
+ ### Operators
34
+ - Arithmetic: +, -, *, /, %
35
+ - Comparison: ==, !=, <, <=, >, >=
36
+ - Assignment: =
37
+ - Logical: and, or, not
38
+
39
+ ### Delimiters
40
+ - Parentheses: ( )
41
+ - Braces: { }
42
+ - Brackets: [ ]
43
+ - Punctuation: , . ; : ->
44
+
45
+ ## Rust Usage
46
+
47
+ ```rust
48
+ use inscript_lexer::Lexer;
49
+
50
+ fn main() {
51
+ let code = "let x = 42;";
52
+ let lexer = Lexer::new(code);
53
+
54
+ for token in lexer {
55
+ match token {
56
+ Ok(t) => println!("{:?}: {}", t.token_type, t.value),
57
+ Err(e) => eprintln!("Error: {}", e),
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ ## Python Usage (after compilation)
64
+
65
+ ```python
66
+ from inscript_lexer import PyLexer, tokenize_string
67
+
68
+ # Method 1: Using PyLexer class
69
+ lexer = PyLexer("let x = 42;")
70
+ tokens = lexer.tokens()
71
+ print(f"Found {lexer.count()} tokens")
72
+
73
+ # Method 2: Direct tokenization
74
+ tokens = tokenize_string("if true then x else y")
75
+ for token in tokens:
76
+ print(f"{token.token_type}: {token.value}")
77
+ ```
78
+
79
+ ## Performance
80
+
81
+ ### Expected Benchmarks
82
+ - Simple tokens: < 100ns per token
83
+ - Complex code: < 10µs per 100 tokens
84
+ - Memory: O(1) per token
85
+
86
+ ### Optimizations
87
+ - Inline hot paths
88
+ - No allocations in common cases
89
+ - SIMD-friendly string scanning
90
+ - Zero-copy string references
91
+
92
+ ## Testing
93
+
94
+ ```bash
95
+ # Run tests
96
+ cargo test
97
+
98
+ # Run with output
99
+ cargo test -- --nocapture
100
+
101
+ # Benchmark
102
+ cargo bench
103
+ ```
104
+
105
+ ## Accuracy
106
+
107
+ ✅ Correct line/column tracking
108
+ ✅ Handles escape sequences
109
+ ✅ Detects unterminated strings
110
+ ✅ Error recovery
111
+
112
+ ## License
113
+
114
+ MIT
115
+
@@ -64,6 +64,13 @@ T_TRANSFORM2D = InScriptType("Transform2D")
64
64
  T_TRANSFORM3D = InScriptType("Transform3D")
65
65
  T_TEXTURE = InScriptType("Texture")
66
66
 
67
+ # Physics built-in types
68
+ T_PHYSICS_WORLD = InScriptType("PhysicsWorld")
69
+ T_BODY = InScriptType("Body")
70
+ T_SHAPE = InScriptType("Shape")
71
+ T_JOINT = InScriptType("Joint")
72
+ T_CONTACT = InScriptType("Contact")
73
+
67
74
  T_NEVER = InScriptType("never") # v1.8.3: bottom type — function never returns normally
68
75
  T_PROMISE = InScriptType("Promise") # v1.9.7: async fn return type
69
76
 
@@ -82,6 +89,9 @@ BUILTIN_TYPES: Dict[str, InScriptType] = {
82
89
  "Color": T_COLOR, "Rect": T_RECT,
83
90
  "Transform2D": T_TRANSFORM2D, "Transform3D": T_TRANSFORM3D,
84
91
  "Texture": T_TEXTURE,
92
+ # physics types
93
+ "PhysicsWorld": T_PHYSICS_WORLD, "Body": T_BODY, "Shape": T_SHAPE,
94
+ "Joint": T_JOINT, "Contact": T_CONTACT,
85
95
  # tuple / array shorthand
86
96
  "Tuple": T_ANY, "List": T_ANY, "Dict": T_ANY, "Map": T_ANY,
87
97
  # v1.9.1: bare 'array' without element type (deprecated — use [T] in v2.0.0)
@@ -515,6 +525,17 @@ class Analyzer(Visitor):
515
525
  Symbol("Vec4", T_VEC4, kind="fn"),
516
526
  Symbol("Color", T_COLOR, kind="fn"),
517
527
  Symbol("Rect", T_RECT, kind="fn"),
528
+ # physics constructors and constants
529
+ Symbol("PhysicsWorld", T_PHYSICS_WORLD, kind="fn"),
530
+ Symbol("PhysicsShape", T_SHAPE, kind="fn"),
531
+ Symbol("BODY_STATIC", T_INT, kind="var"),
532
+ Symbol("BODY_DYNAMIC", T_INT, kind="var"),
533
+ Symbol("BODY_KINEMATIC", T_INT, kind="var"),
534
+ Symbol("JOINT_DISTANCE", T_INT, kind="var"),
535
+ Symbol("JOINT_REVOLUTE", T_INT, kind="var"),
536
+ Symbol("JOINT_PRISMATIC", T_INT, kind="var"),
537
+ Symbol("JOINT_WELD", T_INT, kind="var"),
538
+ Symbol("JOINT_MOUSE", T_INT, kind="var"),
518
539
  # global objects
519
540
  Symbol("input", T_ANY, kind="var"),
520
541
  Symbol("draw", T_ANY, kind="var"),
@@ -1834,6 +1855,10 @@ class Analyzer(Visitor):
1834
1855
  self.visit(node.body)
1835
1856
  return T_VOID
1836
1857
 
1858
+ def visit_TypePattern(self, node: TypePattern) -> InScriptType:
1859
+ self._define(Symbol(node.var_name, T_ANY, kind="var", line=node.line))
1860
+ return T_ANY
1861
+
1837
1862
  def generic_visit(self, node: Node) -> InScriptType:
1838
1863
  # Silently pass through nodes we haven't handled yet
1839
1864
  return T_ANY
@@ -275,6 +275,62 @@ class Compiler:
275
275
  self._eliminate_dead_code(self._proto)
276
276
  return self._proto
277
277
 
278
+ def compile_body(self, body_nodes, params=None, hook_name="<hook>"):
279
+ """Compile a list of AST statement nodes (e.g. hook body) into an FnProto.
280
+
281
+ Unlike compile() which takes a Program AST, this takes raw statement nodes.
282
+ This is used by pygame_backend.py to compile scene hooks to bytecode once,
283
+ then execute them via vm.VM.run() on every frame.
284
+
285
+ Args:
286
+ body_nodes: list of AST statement nodes, or a BlockStmt (which will be
287
+ unwrapped to its .stmts list)
288
+ params: optional list of parameter names (e.g. ['dt'] for on_update)
289
+ hook_name: name for the compiled function (for debugging)
290
+
291
+ Returns:
292
+ FnProto ready to be passed to vm.VM.run()
293
+ """
294
+ # Unwrap BlockStmt if needed
295
+ if hasattr(body_nodes, 'body') and not isinstance(body_nodes, (list, tuple)):
296
+ body_nodes = body_nodes.body
297
+ saved_proto = self._proto
298
+ saved_scope = self._scope
299
+ saved_loop_starts = self._loop_starts
300
+ saved_break_patches = self._break_patches
301
+ saved_cont_patches = self._cont_patches
302
+
303
+ # Create a fresh function scope whose parent is the outer saved scope,
304
+ # so that VarDecl/let creates LOCAL registers instead of STORE_GLOBAL.
305
+ # This mirrors what _fn_decl / _compile_fn do (line 639).
306
+ self._proto = FnProto(hook_name, source_name=self._src)
307
+ self._scope = _Scope(self._proto, parent=saved_scope)
308
+ self._loop_starts = []
309
+ self._break_patches = []
310
+ self._cont_patches = []
311
+
312
+ # Add parameters as locals
313
+ if params:
314
+ for p in params:
315
+ self._scope.add_local(p)
316
+
317
+ # Compile body statements
318
+ for node in body_nodes:
319
+ self._stmt(node)
320
+
321
+ self._e(Op.RETURN, NIL_REG)
322
+ self._eliminate_dead_code(self._proto)
323
+ result = self._proto
324
+
325
+ # Restore
326
+ self._proto = saved_proto
327
+ self._scope = saved_scope
328
+ self._loop_starts = saved_loop_starts
329
+ self._break_patches = saved_break_patches
330
+ self._cont_patches = saved_cont_patches
331
+
332
+ return result
333
+
278
334
  def _eliminate_dead_code(self, proto):
279
335
  """v1.3.0: remove unreachable instructions after unconditional JUMP/RETURN."""
280
336
  code = proto.code
@@ -1358,3 +1414,14 @@ def compile_source(source, filename="<script>"):
1358
1414
  toks = Lexer(source, filename).tokenize()
1359
1415
  prog = Parser(toks, source).parse()
1360
1416
  return Compiler(filename).compile(prog)
1417
+
1418
+
1419
+ def compile_body(body_nodes, params=None, hook_name="<hook>", source_name="<script>"):
1420
+ """Convenience: compile a list of AST statement nodes to FnProto.
1421
+
1422
+ Usage:
1423
+ from compiler import compile_body
1424
+ proto = compile_body(hook.body, params=['dt'], hook_name='on_update')
1425
+ vm.run(proto)
1426
+ """
1427
+ return Compiler(source_name).compile_body(body_nodes, params, hook_name)
@@ -24,7 +24,7 @@ from errors import (InScriptError, LexerError, ParseError,
24
24
  SemanticError, InScriptRuntimeError,
25
25
  MultiError, InScriptWarning)
26
26
 
27
- VERSION = "3.0.0"
27
+ VERSION = "3.9.6.23"
28
28
 
29
29
  MANIFEST_FILENAME = "inscript.toml"
30
30
  LOCK_FILENAME = "inscript.lock"
@@ -2386,7 +2386,8 @@ def run_source(source: str, filename: str = "<stdin>",
2386
2386
  warn_as_error: bool = False,
2387
2387
  strict: bool = False,
2388
2388
  profile: bool = False,
2389
- json_errors: bool = False) -> int:
2389
+ json_errors: bool = False,
2390
+ debug: bool = False) -> int:
2390
2391
  """Lex, parse, analyze, and interpret InScript source code."""
2391
2392
 
2392
2393
  def _emit_error(e):
@@ -2443,7 +2444,7 @@ def run_source(source: str, filename: str = "<stdin>",
2443
2444
 
2444
2445
  # ── 4. Interpret — Phase 3: Python-leak guard ─────────────────────────
2445
2446
  try:
2446
- interp = Interpreter(source.splitlines(), filename=filename)
2447
+ interp = Interpreter(source.splitlines(), filename=filename, debug=debug)
2447
2448
  if profile:
2448
2449
  import cProfile, pstats, io as _io
2449
2450
  pr = cProfile.Profile()
@@ -2660,7 +2661,11 @@ Examples:
2660
2661
  parser.add_argument("--doc-out", metavar="DIR", default=None,
2661
2662
  help="v1.9.3: Output directory for --doc (default: stdout / docs/api/)")
2662
2663
  parser.add_argument("--errors", metavar="PREFIX", nargs="?", const="",
2663
- help="v1.9.4: Print error code catalogue (optional prefix filter, e.g. E003)")
2664
+ help="v1.9.4: Print error code catalogue (optional prefix filter, e.g. E003)")
2665
+ parser.add_argument("--rust", action="store_true",
2666
+ help="[DEPRECATED] Rust is now the default — use --python to opt out")
2667
+ parser.add_argument("--python", action="store_true",
2668
+ help="Use the Python tree-walk interpreter instead of the Rust VM")
2664
2669
  parser.add_argument("--changelog", metavar="RANGE",
2665
2670
  help="v1.9.4: Print changelog for version range e.g. v1.6.0..v1.9.4")
2666
2671
  parser.add_argument("--benchmark", metavar="NAME", nargs="?", const="",
@@ -2684,7 +2689,11 @@ Examples:
2684
2689
  parser.add_argument("--warn-as-error", action="store_true",
2685
2690
  help="Treat any warning as an error (CI strictness)")
2686
2691
  parser.add_argument("--profile", action="store_true",
2687
- help="Print per-function call count and timing after execution")
2692
+ help="Print per-function call count and timing after execution")
2693
+ parser.add_argument("--debug", action="store_true",
2694
+ help="v3.9.6.10: Run in debug mode with breakpoint support")
2695
+ parser.add_argument("--dap", action="store_true",
2696
+ help="v3.9.6.13: Start DAP server for VS Code debugging (uses --debug)")
2688
2697
  parser.add_argument("--fmt", action="store_true",
2689
2698
  help="Format .ins files: inscript --fmt file.ins")
2690
2699
  parser.add_argument("--fmt-all", metavar="DIR",
@@ -2773,6 +2782,12 @@ Examples:
2773
2782
  help="Window height for --game mode (default: 600)")
2774
2783
  parser.add_argument("--fps", type=int, default=60,
2775
2784
  help="Target FPS for --game mode (default: 60)")
2785
+ parser.add_argument("--batch-draw", action="store_true",
2786
+ help="Batch draw ops (--game mode only)")
2787
+ parser.add_argument("--frame-break", type=int, default=-1,
2788
+ help="v3.9.6.14: Break at specific frame (--game mode only)")
2789
+ parser.add_argument("--frame-advance", action="store_true",
2790
+ help="v3.9.6.14: Step one frame at a time (--game mode only)")
2776
2791
  # ── v2.4.0: compilation flags ────────────────────────────────────────────
2777
2792
  parser.add_argument("--compile", metavar="FILE",
2778
2793
  help="v2.4.0: AOT-compile FILE.ins → FILE.ibc bytecode")
@@ -2787,6 +2802,10 @@ Examples:
2787
2802
  help="v2.4.0: Skip recompile if .ibc is newer than source")
2788
2803
  args = parser.parse_args()
2789
2804
 
2805
+ # Backward compat: --rust is now the default, warn and ignore
2806
+ if getattr(args, 'rust', False):
2807
+ print("[InScript] Warning: --rust is now the default (no flag needed). Use --python to use the Python interpreter.", file=sys.stderr)
2808
+
2790
2809
  if args.version:
2791
2810
  print(f"InScript {VERSION}")
2792
2811
  return
@@ -2936,7 +2955,12 @@ Examples:
2936
2955
  from pygame_backend import run_scene
2937
2956
  run_scene(args.file,
2938
2957
  width=args.width, height=args.height, fps=args.fps,
2939
- title=os.path.basename(args.file))
2958
+ title=os.path.basename(args.file),
2959
+ profile=getattr(args, 'profile', False),
2960
+ batch_draw=getattr(args, 'batch_draw', False),
2961
+ debug=getattr(args, 'debug', False),
2962
+ frame_break=getattr(args, 'frame_break', -1),
2963
+ frame_advance=getattr(args, 'frame_advance', False))
2940
2964
  return 0
2941
2965
  except ImportError:
2942
2966
  print("[InScript] pygame_backend not found next to inscript.py", file=sys.stderr)
@@ -3200,6 +3224,20 @@ Examples:
3200
3224
  print(e, file=sys.stderr); return 1
3201
3225
  return 0
3202
3226
 
3227
+ # Rust compiler/VM fast path (default). Use --python to use the Python interpreter.
3228
+ if not getattr(args, 'python', False):
3229
+ try:
3230
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "target", "release"))
3231
+ from inscript_parser import compile_and_run
3232
+ result = compile_and_run(source)
3233
+ print(result)
3234
+ return 0
3235
+ except ImportError:
3236
+ print("[InScript] Rust VM not available — falling back to Python interpreter", file=sys.stderr)
3237
+ except Exception as e:
3238
+ print(f"[Rust VM] Error: {e}", file=sys.stderr)
3239
+ return 1
3240
+
3203
3241
  # Normal run
3204
3242
  type_check = not getattr(args, 'no_typecheck', False) and \
3205
3243
  not getattr(args, 'unsafe_no_check', False)
@@ -3208,13 +3246,27 @@ Examples:
3208
3246
  strict = getattr(args, "strict", False)
3209
3247
  warn_as_error = getattr(args, "warn_as_error", False) or strict
3210
3248
  profile = getattr(args, "profile", False)
3249
+ debug_mode = getattr(args, "debug", False)
3250
+ dap_mode = getattr(args, "dap", False)
3251
+
3252
+ if dap_mode:
3253
+ _here = os.path.dirname(os.path.abspath(__file__))
3254
+ sys.path.insert(0, _here)
3255
+ from interpreter import Interpreter
3256
+ from debugger import Debugger
3257
+ from dap_server import DAPServer
3258
+ interp = Interpreter(source_lines=[], debug=True)
3259
+ dbger = Debugger(interp, filename=args.file)
3260
+ dap = DAPServer(interp, dbger, args.file)
3261
+ dap.run()
3262
+ return 0
3211
3263
 
3212
3264
  with open(args.file, "r", encoding="utf-8") as _f:
3213
3265
  _source = _f.read()
3214
3266
  return run_source(_source, filename=args.file, type_check=type_check,
3215
3267
  no_warn=no_warn, no_warn_unused=no_warn_unused,
3216
3268
  warn_as_error=warn_as_error, strict=strict,
3217
- profile=profile,
3269
+ profile=profile, debug=debug_mode,
3218
3270
  json_errors=getattr(args, 'json_errors', False))
3219
3271
 
3220
3272
 
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: inscript-lang
3
+ Version: 3.9.6.23
4
+ Summary: InScript — a game-focused scripting language with 59 game modules and a bytecode VM
5
+ Home-page: https://github.com/authorss81/inscript
6
+ Author: Shreyasi Sarkar
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/authorss81/inscript
9
+ Project-URL: Repository, https://github.com/authorss81/inscript
10
+ Project-URL: Bug Tracker, https://github.com/authorss81/inscript/issues
11
+ Project-URL: Documentation, https://authorss81.github.io/inscript/docs/
12
+ Keywords: game,scripting,language,gamedev,gdscript
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Games/Entertainment
21
+ Classifier: Topic :: Software Development :: Interpreters
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ Provides-Extra: game
25
+ Requires-Dist: pygame>=2.0; extra == "game"
26
+ Provides-Extra: lsp
27
+ Requires-Dist: pygls>=1.0; extra == "lsp"
28
+ Provides-Extra: all
29
+ Requires-Dist: pygame>=2.0; extra == "all"
30
+ Requires-Dist: pygls>=1.0; extra == "all"
31
+ Dynamic: home-page
32
+ Dynamic: requires-python
33
+
34
+ # InScript Lexer - Rust Implementation (v3.7.2)
35
+
36
+ **Real, compilable Rust tokenizer** for InScript language.
37
+
38
+ ## Features
39
+
40
+ ✅ Zero-copy token references (fast, memory efficient)
41
+ ✅ State machine lexer (no backtracking)
42
+ ✅ 30+ token types (keywords, operators, literals)
43
+ ✅ Accurate line/column tracking
44
+ ✅ Comprehensive error reporting
45
+ ✅ Python FFI via PyO3
46
+ ✅ Full test coverage
47
+
48
+ ## Build
49
+
50
+ ```bash
51
+ cargo build --release
52
+ ```
53
+
54
+ ## Token Types Supported
55
+
56
+ ### Literals
57
+ - Numbers (integers and floats)
58
+ - Strings (single and double quoted)
59
+ - Identifiers
60
+
61
+ ### Keywords
62
+ - if, else, while, for, fn, return
63
+ - true, false, nil
64
+ - and, or, not
65
+
66
+ ### Operators
67
+ - Arithmetic: +, -, *, /, %
68
+ - Comparison: ==, !=, <, <=, >, >=
69
+ - Assignment: =
70
+ - Logical: and, or, not
71
+
72
+ ### Delimiters
73
+ - Parentheses: ( )
74
+ - Braces: { }
75
+ - Brackets: [ ]
76
+ - Punctuation: , . ; : ->
77
+
78
+ ## Rust Usage
79
+
80
+ ```rust
81
+ use inscript_lexer::Lexer;
82
+
83
+ fn main() {
84
+ let code = "let x = 42;";
85
+ let lexer = Lexer::new(code);
86
+
87
+ for token in lexer {
88
+ match token {
89
+ Ok(t) => println!("{:?}: {}", t.token_type, t.value),
90
+ Err(e) => eprintln!("Error: {}", e),
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Python Usage (after compilation)
97
+
98
+ ```python
99
+ from inscript_lexer import PyLexer, tokenize_string
100
+
101
+ # Method 1: Using PyLexer class
102
+ lexer = PyLexer("let x = 42;")
103
+ tokens = lexer.tokens()
104
+ print(f"Found {lexer.count()} tokens")
105
+
106
+ # Method 2: Direct tokenization
107
+ tokens = tokenize_string("if true then x else y")
108
+ for token in tokens:
109
+ print(f"{token.token_type}: {token.value}")
110
+ ```
111
+
112
+ ## Performance
113
+
114
+ ### Expected Benchmarks
115
+ - Simple tokens: < 100ns per token
116
+ - Complex code: < 10µs per 100 tokens
117
+ - Memory: O(1) per token
118
+
119
+ ### Optimizations
120
+ - Inline hot paths
121
+ - No allocations in common cases
122
+ - SIMD-friendly string scanning
123
+ - Zero-copy string references
124
+
125
+ ## Testing
126
+
127
+ ```bash
128
+ # Run tests
129
+ cargo test
130
+
131
+ # Run with output
132
+ cargo test -- --nocapture
133
+
134
+ # Benchmark
135
+ cargo bench
136
+ ```
137
+
138
+ ## Accuracy
139
+
140
+ ✅ Correct line/column tracking
141
+ ✅ Handles escape sequences
142
+ ✅ Detects unterminated strings
143
+ ✅ Error recovery
144
+
145
+ ## License
146
+
147
+ MIT
148
+
@@ -32,5 +32,17 @@ inscript_lang.egg-info/PKG-INFO
32
32
  inscript_lang.egg-info/SOURCES.txt
33
33
  inscript_lang.egg-info/dependency_links.txt
34
34
  inscript_lang.egg-info/entry_points.txt
35
+ inscript_lang.egg-info/not-zip-safe
35
36
  inscript_lang.egg-info/requires.txt
36
- inscript_lang.egg-info/top_level.txt
37
+ inscript_lang.egg-info/top_level.txt
38
+ inscript_rust_parser/Cargo.toml
39
+ lsp/__init__.py
40
+ lsp/code_actions.py
41
+ lsp/completions.py
42
+ lsp/definition.py
43
+ lsp/diagnostics.py
44
+ lsp/hover.py
45
+ lsp/semantic_tokens.py
46
+ lsp/server.py
47
+ tools/__init__.py
48
+ tools/sync_versions.py