InScript - A modern scripting language with generics, ADT enums, coroutines, and more
Project description
๐ฎ InScript
A modern programming language designed for games โ clean syntax, powerful type system, batteries included.
What is InScript?
InScript is a statically-typed, dynamically-executed scripting language built specifically for game development. It brings Rust-style safety (pattern matching, ADT enums, Result types, generics) with Python-like readability โ and runs right out of the box with a single Python file.
// Structs with inheritance and operator overloading
struct Ship {
x: float y: float hp: int
fn take_damage(amount: int) { self.hp -= amount }
}
struct PlayerShip extends Ship {
shots: int
fn fire() -> string {
self.shots += 1
return f"๐ฅ Shot #{self.shots}!"
}
}
// ADT enums with pattern matching
enum Asteroid {
Small(x: float, y: float)
Large(x: float, y: float)
}
fn points(a: Asteroid) -> int {
match a {
case Small(x, y) { return 30 }
case Large(x, y) { return 10 }
}
}
// Generic data structures
struct Stack<T> {
items: T[]
fn push(item: T) { self.items.push(item) }
fn pop() -> T { return self.items.pop() }
}
// Error propagation
fn accuracy(hits: int, shots: int) -> Result {
let r = safe_divide(float(hits), float(shots))?
return Ok(r * 100.0)
}
// Coroutines
fn* spawn_wave(n: int) {
let i = 0
while i < n { yield Asteroid.Large(random_int(0,800), 0.0); i += 1 }
}
Feature Overview
| Feature | Status | Notes |
|---|---|---|
Variables (let, const) with type annotations |
โ | Type inference supported |
| Structs with methods | โ | Full OOP |
Struct inheritance (extends) |
โ | Method dispatch + field inheritance |
| Interface / Trait system | โ | interface + implements |
Operator overloading (fn +()) |
โ | All arithmetic + comparison ops |
Mixins (with keyword) |
โ | Horizontal code reuse |
Properties (get/set) |
โ | Computed + validated fields |
| Static methods | โ | static fn on structs |
Generics (struct Stack<T>) |
โ | Type-erased, multi-param |
| ADT Enums with data fields | โ | Circle(radius: float) |
| Pattern matching + guards | โ | case v if v < 10 |
| ADT destructuring | โ | case Circle(r) binds r |
Error propagation ? |
โ | Ok(v) / Err(e) / Result? |
| Coroutines / generators | โ | fn* + yield + .next() |
| Comptime evaluation | โ | comptime { 1024 * 4 } |
Pipe operator |> (chainable) |
โ | x |> double |> add1 |
| Destructuring | โ | let [a,b] = arr / let {x,y} = p |
| Spread operator | โ | fn sum(...args) / call(...arr) |
| Optional chaining | โ | obj?.field?.method() |
| Nullish coalescing | โ | value ?? "default" |
| F-strings | โ | f"Hello {name}!" |
| Multi-line strings | โ | """...""" |
| Closures / lambdas | โ | |x| x * 2 |
| Async/await syntax | โ | |
| Labeled break/continue | โ | outer: for ... { break outer } |
| Built-in math, Vec2, Vec3, Color | โ | Game-ready primitives |
| REPL | โ | Interactive shell |
Quick Start
1. Clone and run (no install needed)
git clone https://github.com/YOUR_USERNAME/inscript.git
cd inscript
python inscript.py examples/asteroid_blaster.ins
2. Try the REPL
python inscript.py --repl
InScript 0.6.0 REPL โ type 'exit' or Ctrl+C to quit
>> let x = 42
>> print(f"The answer is {x}")
The answer is 42
>> struct Point { x: float y: float }
>> let p = Point { x: 3.0, y: 4.0 }
>> print(p.x)
3.0
3. Run any .ins file
python inscript.py mygame.ins
Running in VS Code
Prerequisites
- VS Code installed
- Python extension for VS Code installed
- Python 3.10+ on your system (
python --version)
Step-by-step
1. Clone the repo and open in VS Code
git clone https://github.com/YOUR_USERNAME/inscript.git
cd inscript
code .
2. Set Python interpreter
Press Ctrl+Shift+P โ type Python: Select Interpreter โ choose Python 3.10+
3. Open the example program
In the Explorer panel, open examples/asteroid_blaster.ins to browse the code.
4. Create a run task โ create .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Run InScript file",
"type": "shell",
"command": "python",
"args": ["${workspaceFolder}/inscript.py", "${file}"],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": []
},
{
"label": "Run example: Asteroid Blaster",
"type": "shell",
"command": "python",
"args": ["${workspaceFolder}/inscript.py", "examples/asteroid_blaster.ins"],
"group": "build",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": []
},
{
"label": "InScript REPL",
"type": "shell",
"command": "python",
"args": ["${workspaceFolder}/inscript.py", "--repl"],
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
},
"problemMatcher": []
}
]
}
5. Run it!
- Press
Ctrl+Shift+Bto run the currently open.insfile - Or open Command Palette โ
Tasks: Run Taskโ choose any task above
Tip: Add this launch.json for F5 debugging too (.vscode/launch.json):
{
"version": "0.2.0",
"configurations": [
{
"name": "Run InScript (current file)",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/inscript.py",
"args": ["${file}"],
"console": "integratedTerminal"
}
]
}
Now pressing F5 while editing any .ins file will run it through InScript.
Language Tour
Variables & Types
let x: int = 42
let name = "Ada" // type inferred
const MAX = comptime { 1024 * 4 } // compile-time constant = 4096
Functions
fn lerp(a: float, b: float, t: float) -> float {
return a + (b - a) * t
}
// Closures
let doubled = [1, 2, 3].map(|x| x * 2)
Structs
struct Bullet extends Entity {
dmg: int = 10
speed: float = 600.0
fn update(dt: float) {
self.pos += Vec2(0.0, -self.speed * dt)
}
}
Generics
struct Pair<A, B> {
first: A
second: B
}
let p = Pair<int, string> { first: 1, second: "one" }
ADT Enums + Pattern Matching
enum Shape {
Circle(radius: float)
Rectangle(w: float, h: float)
}
fn area(s: Shape) -> float {
match s {
case Circle(r) { return 3.14159 * r * r }
case Rectangle(w, h) { return w * h }
}
}
Error Handling
fn load(path: string) -> Result {
let data = read_file(path)? // propagates Err upward
return Ok(data)
}
let result = load("level.json")
let data = unwrap_or(result, "{}")
Coroutines
fn* enemy_spawner() {
while true {
yield Enemy { x: random_int(0, 800), y: -20 }
}
}
let spawner = enemy_spawner()
let enemy = spawner.next()
Pipe Operator
fn clamp01(v: float) -> float { return clamp(v, 0.0, 1.0) }
fn to_pct(v: float) -> string { return f"{v * 100.0}%" }
let display = raw_value |> clamp01 |> to_pct
// โ "73.5%"
Project Structure
inscript/
โโโ inscript.py โ Entry point (run files, REPL, flags)
โโโ lexer.py โ Tokenizer
โโโ parser.py โ Recursive-descent parser โ AST
โโโ ast_nodes.py โ All AST node dataclasses
โโโ interpreter.py โ Tree-walk interpreter (122 tests)
โโโ analyzer.py โ Static type analyzer
โโโ environment.py โ Scope / variable resolution
โโโ errors.py โ Error + signal classes
โโโ stdlib.py โ Standard library
โโโ stdlib_values.py โ Runtime value types (InScriptRange, etc.)
โโโ repl.py โ Interactive REPL
โโโ setup.py โ PyPI packaging
โโโ examples/
โ โโโ asteroid_blaster.ins โ Full demo program
โโโ tests/
โโโ test_interpreter.py โ 122 runtime tests
โโโ test_parser.py
โโโ test_lexer.py
โโโ test_analyzer.py
โโโ test_stdlib.py
Testing
# Run all interpreter tests (122 tests)
python test_interpreter.py
# Run parser tests
python test_parser.py
# Run lexer tests
python test_lexer.py
Expected output:
=================================================================
Phase 4 Final Results
=================================================================
122 passed, 0 failed out of 122 tests
=================================================================
CLI Reference
python inscript.py <file.ins> # Run a file
python inscript.py --repl # Interactive REPL
python inscript.py --check <file.ins> # Type-check only (no run)
python inscript.py --tokens <file.ins># Print lexer tokens
python inscript.py --ast <file.ins> # Print the AST
python inscript.py --version # Print version
Roadmap
- Union / intersection types (
Shape = Circle | Rectangle) - Abstract methods (
abstract fn update()) - Macro / metaprogramming system
- SIMD vector types (
float32x4) - LSP VS Code extension (syntax highlighting + completions)
- PyPI package (
pip install inscript-lang)
License
MIT โ see LICENSE
Built with โค๏ธ and Python ยท InScript 0.6.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inscript_lang-0.6.0.tar.gz.
File metadata
- Download URL: inscript_lang-0.6.0.tar.gz
- Upload date:
- Size: 76.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0666a9e44fbace9fafc55c3611a3b840d0a16ab46be0cf85ef8202f41fadcde
|
|
| MD5 |
b32dc6bb9780d27419d7c47c849bec69
|
|
| BLAKE2b-256 |
08225afefd3129cbd1eda2af154eeb9a9b75cc92e9926a21c3627c5f68c03fe9
|
File details
Details for the file inscript_lang-0.6.0-py3-none-any.whl.
File metadata
- Download URL: inscript_lang-0.6.0-py3-none-any.whl
- Upload date:
- Size: 75.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2460617884e09a411dd90eb830dc0579b96d29e530d8b246645fb8931e08d70a
|
|
| MD5 |
82fd86692899f4376aaf239e450bcfe3
|
|
| BLAKE2b-256 |
b612dce7a060c59ec16fcc6edee16a5c2ed12f26cb7f962557b0ad384c29d2db
|