@inglorious/babel-plugin-inglorious-script
v1.3.2
Published
A Babel plugin for the IngloriousScript language.
Maintainers
Readme
Babel Plugin: IngloriousScript
@inglorious/babel-plugin-inglorious-script is a Babel plugin that transforms your JavaScript code into IngloriousScript, a superset of JavaScript that provides intuitive, operator-overloaded vector math.
This allows you to write vector operations using familiar arithmetic operators (+, -, *, /, etc.), making your game logic cleaner, more readable, and less error-prone. The plugin uses hybrid static/runtime analysis to provide both compile-time optimizations and runtime safety for complex scenarios.
Why IngloriousScript?
Working with vectors in game development often involves verbose and repetitive function calls:
// Before: Standard JavaScript
import { add, scale, mod } from "@inglorious/utils/math/vectors.js"
const newPosition = mod(add(position, scale(velocity, dt)), worldSize)With IngloriousScript, you can write the same logic as a natural mathematical expression:
// After: IngloriousScript
const newPosition = (position + velocity * dt) % worldSizeThe plugin handles the transformation, giving you clean syntax with efficient execution and automatic type safety.
Features
- Intuitive Syntax: Use standard math operators for vector arithmetic
- Hybrid Analysis: Static optimization when types are certain, runtime safety when they're not
- Automatic Vector Preservation: Maintains vector properties through component assignments and array operations
- Mutative Integration: Works seamlessly with state management libraries that modify object properties
- Comprehensive Operator Support: Binary, unary, and compound assignment operators
- Smart Error Detection: Catches mathematical errors at compile-time when possible
Installation
First, install the plugin using your package manager:
npm install -D @inglorious/babel-plugin-inglorious-script
# or
yarn add -D @inglorious/babel-plugin-inglorious-script
# or
pnpm add -D @inglorious/babel-plugin-inglorious-scriptThen, add it to your Babel configuration file (e.g., .babelrc.json):
{
"plugins": ["inglorious-script"]
}Usage
The plugin automatically detects vectors created with the v function and transforms the operations they are involved in. You don't need to manually import the v function - the plugin will automatically inject the import when it detects usage.
Supported Operations
Vector-Vector Operations
Addition and subtraction between two vectors work as you'd expect:
// No import needed - the plugin automatically adds it
const v1 = v(10, 20)
const v2 = v(1, 2)
const sum = v1 + v2 // Becomes sum(v1, v2)
const difference = v1 - v2 // Becomes subtract(v1, v2)Component-wise multiplication is also supported:
const v1 = v(2, 3)
const v2 = v(4, 5)
const hadamardProduct = v1 * v2 // Becomes multiply(v1, v2) -> v(8, 15)Vector-Scalar Operations
You can use *, /, %, and ** to operate on a vector with a scalar. The order of operands is flexible for all operators:
const v1 = v(10, 20)
const s = 2
// Vector-first operations
const r1 = v1 * s // scale(v1, s)
const r2 = v1 / s // divide(v1, s)
const r3 = v1 % s // mod(v1, s)
const r4 = v1 ** s // power(v1, s)
// Scalar-first operations
const r5 = s * v1 // scale(v1, s)
const r6 = s / v1 // divideBy(s, v1)
const r7 = s % v1 // modOf(s, v1)
const r8 = s ** v1 // powerOf(s, v1)Unary Operations
Negate a vector using the unary minus operator:
const v1 = v(5, -10)
const negated = -v1 // Becomes scale(v1, -1)Compound Assignments
Compound assignment operators are fully supported for in-place modifications:
let position = v(0, 0)
const velocity = v(1, 2)
position += velocity // position = sum(position, velocity)
position *= 2 // position = scale(position, 2)Supported assignment operators: +=, -=, *=, /=, %=, **=.
Component-Wise Operations
You can modify individual vector components, and the plugin automatically preserves the vector's type properties:
const entity = { position: v(10, 20) }
// Modify a single component
entity.position[0] += deltaX
// Automatically becomes: (entity.position[0] += deltaX, entity.position = ensureV(entity.position))
// Works with any computed access
entity.position[X] = newX
entity.position[Y] *= scaleFactorThis is especially useful when working with Mutative or other libraries that might strip custom properties from objects.
Array Method Support
Vector objects support standard array methods, and the plugin automatically preserves their vector nature:
const velocity = v(1, 2, 3)
// These all maintain vector properties:
const doubled = velocity.map((x) => x * 2) // ensureV(velocity.map(x => x * 2))
const positive = velocity.filter((x) => x > 0) // ensureV(velocity.filter(x => x > 0))
const xy = velocity.slice(0, 2) // ensureV(velocity.slice(0, 2))
const extended = velocity.concat([4]) // ensureV(velocity.concat([4]))
// Even reduce operations are handled intelligently:
const magnitude = velocity.reduce((sum, x) => sum + x * x, 0) // Returns scalar (no wrapping)
const doubled2 = velocity.reduce((acc, x) => [...acc, x * 2], []) // Returns vector (wrapped)Hybrid Static/Runtime Analysis
The plugin uses intelligent analysis to optimize your code:
Compile-Time Optimization
When variable types are certain, operations are optimized at compile-time and invalid operations are caught early:
const v1 = v(1, 2)
const v2 = v(3, 4)
// This throws a compile-time error:
const result = v1 * v2
// Error: Cannot multiply two vectors. Did you mean dot product (dot(v1, v2)) or cross product (cross(v1, v2))?
// This is optimized to a direct function call:
const sum = v1 + v2 // Directly becomes sum(v1, v2)Runtime Safety
When operand types can't be determined at compile-time (function returns, complex expressions, etc.), the plugin generates runtime helpers that handle all valid combinations:
import { getForce } from "./physics.js"
let velocity = v(0, 0)
const force = getForce() // Could return vector or scalar
// The plugin generates runtime type checking:
velocity += force
// Becomes: velocity = __vectorSum(velocity, force)
// The helper handles vector+vector, but throws error for vector+scalarFunction Call Integration
The plugin handles complex expressions involving function calls:
function getVector() {
return v(1, 2)
}
function getScalar() {
return 5
}
// This works correctly with runtime type checking:
const result = getVector() * getScalar() + v(3, 4)Mutative and State Management Integration
The plugin works seamlessly with Mutative and other state management libraries:
import { create } from "mutative"
const gameState = {
player: {
position: v(10, 20),
velocity: v(1, 2),
},
}
const newState = create(gameState, (draft) => {
// Even though Mutative creates plain objects, these operations work:
draft.player.position += draft.player.velocity
draft.player.position[0] *= 1.1 // Component assignment with auto-restoration
})Error Handling
The plugin provides helpful error messages for common mistakes:
const velocity = v(5, 10)
const position = v(0, 0)
// Compile-time errors (when types are certain):
position + 5 // Error: Cannot add a vector and a non-vector
velocity * position // Error: Cannot multiply two vectors
// Runtime errors (when types are uncertain):
someFunction() + anotherFunction() // Runtime type checking with appropriate errorsHow It Works
@inglorious/babel-plugin-inglorious-script uses sophisticated AST analysis to:
- Auto-Import Management: Automatically detects when
v()is used and injects the necessary imports - Track Vector Types: Follows variable assignments and function calls to understand when values are vectors
- Static Optimization: When types are certain, generates optimized function calls and catches errors early
- Runtime Safety: When types are uncertain, generates helpers that perform runtime type checking
- Property Preservation: Automatically maintains vector properties through component assignments and array operations
- Helper Injection: Automatically imports and injects necessary helper functions and utilities
The plugin generates efficient code that balances performance with safety, ensuring your vector math is both fast and correct without requiring manual imports.
Requirements
This plugin requires:
@inglorious/utilspackage for vector operations and utilities- Babel 7.x or higher
- Node.js 16 or higher
License
MIT License - Free and open source
Created by Matteo Antony Mistretta
You're free to use, modify, and distribute this software. See LICENSE for details.
