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.
- inscript_lang-3.9.6.23/PKG-INFO +148 -0
- inscript_lang-3.9.6.23/README.md +115 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/analyzer.py +25 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/compiler.py +67 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript.py +59 -7
- inscript_lang-3.9.6.23/inscript_lang.egg-info/PKG-INFO +148 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/SOURCES.txt +13 -1
- inscript_lang-3.9.6.23/inscript_lang.egg-info/not-zip-safe +1 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/top_level.txt +2 -0
- inscript_lang-3.9.6.23/inscript_rust_parser/Cargo.toml +17 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/interpreter.py +211 -10
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/lexer.py +196 -9
- inscript_lang-3.9.6.23/lsp/__init__.py +6 -0
- inscript_lang-3.9.6.23/lsp/code_actions.py +95 -0
- inscript_lang-3.9.6.23/lsp/completions.py +189 -0
- inscript_lang-3.9.6.23/lsp/definition.py +144 -0
- inscript_lang-3.9.6.23/lsp/diagnostics.py +58 -0
- inscript_lang-3.9.6.23/lsp/hover.py +128 -0
- inscript_lang-3.9.6.23/lsp/semantic_tokens.py +134 -0
- inscript_lang-3.9.6.23/lsp/server.py +346 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/parser.py +9 -4
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/pygame_backend.py +382 -19
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/pyproject.toml +4 -1
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/repl.py +1 -1
- inscript_lang-3.9.6.23/setup.py +126 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib.py +7 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_assets.py +6 -1
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_game.py +111 -3
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/studio_bridge.py +72 -2
- inscript_lang-3.9.6.23/tools/__init__.py +0 -0
- inscript_lang-3.9.6.23/tools/sync_versions.py +80 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/vm.py +50 -4
- inscript_lang-3.0.0/PKG-INFO +0 -210
- inscript_lang-3.0.0/README.md +0 -179
- inscript_lang-3.0.0/inscript_lang.egg-info/PKG-INFO +0 -210
- inscript_lang-3.0.0/setup.py +0 -75
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/ast_nodes.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/environment.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/errors.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/export_pipeline.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/hot_reload.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_dap.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_fmt.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/dependency_links.txt +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/entry_points.txt +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_lang.egg-info/requires.txt +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_studio_api.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/inscript_test.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/scene_tree.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/setup.cfg +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_extended.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_extended_2.py +0 -0
- {inscript_lang-3.0.0 → inscript_lang-3.9.6.23}/stdlib_values.py +0 -0
- {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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|