A JavaScript-inspired interpreted programming language with C++-like structure, built in Node.js.
- Numbers:
intandfloat(automatic detection) - Strings:
"hello world" - Booleans:
true,false - Null:
null - Arrays:
[1, 2, 3, "hello"] - Objects:
{name: "Alice", age: 30} - Regular Expressions:
/pattern/flags(viaRegExp()constructor) - Sets:
new Set([1, 2, 3]) - Maps:
new Map([["key", "value"]])
- Variables:
var name = value; - Functions:
function name(params) { ... } - Async Functions:
async function name(params) { ... } - Arrow Functions:
x => x * 2,(a, b) => a + b - Async Arrow Functions:
async x => await someAsyncOp(x) - Classes:
class MyClass { constructor() { ... } method() { ... } async asyncMethod() { ... } } - Inheritance:
class ChildClass extends ParentClass { ... } - Object Instantiation:
var obj = new MyClass(); thiskeyword: Refers to the current object instance within methods.superkeyword: Used to call methods on the superclass.awaitkeyword: Pause execution until a Promise resolves (only insideasyncfunctions).- Control Flow:
if/else,whileloops,forloops - For-In Loops:
for (var key in object)andfor (var index in array) - Loop Control:
breakandcontinuestatements - Exception Handling:
try/catch/finally,throw - Modules:
import,export,from,as,defaultfor organizing code. - Operators: Arithmetic (
+,-,*,/,%), Comparison (==,!=,>,<,>=,<=), Logical (&&,||,!) - Ternary:
condition ? true_value : false_value - Array Access:
array[index] - Object/Instance Access:
object.propertyorobject["property"]
print(...)- Output to consolelen(value)- Get length of string, array, object, Set, or Maptypeof(value)- Get type of valuedelay(milliseconds)- Returns a Promise that resolves after a given time (for async examples)
push(array, value)- Add element to arraypop(array)- Remove and return last element from array
map(array, function)- Transform each element using a functionfilter(array, function)- Keep elements that match a conditionreduce(array, function, initialValue)- Combine all elements into single valuefind(array, function)- Get first element that matches conditionsome(array, function)- Check if any element matches conditionevery(array, function)- Check if all elements match conditionforEach(array, function)- Execute function for each elementindexOf(array, element)- Find index of element (-1 if not found)includes(array, element)- Check if array contains elementslice(array, start, end)- Extract portion of arraysplice(array, start, deleteCount, ...items)- Modify array by removing/adding elements
keys(object)- Get array of object keysvalues(object)- Get array of object valueshasOwnProperty(object, property)- Check if object has propertyassign(target, ...sources)- Copy properties from source objects to target
abs(number)- Absolute valuefloor(number)- Floor functionceil(number)- Ceiling functionround(number)- Round to nearest integersqrt(number)- Square rootpow(base, exp)- Power function
RegExp(pattern, flags)- Constructor to create a regular expression object.pattern: A string containing the regular expression pattern.flags: An optional string containing flags (e.g., "g" for global, "i" for case-insensitive).- Returns a RegExp object with methods:
regex.test(string): Returnstrueif the regex matches the string,falseotherwise.regex.exec(string): Returns an array of match results ornull.regex.source: Returns the source pattern string.regex.flags: Returns the flags string.
Set(iterable)- Constructor to create a Set object.iterable: An optional array or other iterable to initialize the set.- Returns a Set object with methods:
set.add(value): Adds a value to the set.set.delete(value): Deletes a value from the set.set.has(value): Returnstrueif a value is in the set.set.clear(): Removes all elements from the set.set.size: Returns the number of elements in the set.
Map(iterable)- Constructor to create a Map object.iterable: An optional array of[key, value]pairs or other iterable to initialize the map.- Returns a Map object with methods:
map.set(key, value): Sets a value for a key in the map.map.get(key): Returns the value associated with the key.map.delete(key): Deletes a key-value pair from the map.map.has(key): Returnstrueif a key exists in the map.map.clear(): Removes all key-value pairs from the map.map.size: Returns the number of key-value pairs in the map.map.keys(): Returns an array of keys in insertion order.map.values(): Returns an array of values in insertion order.map.entries(): Returns an array of[key, value]pairs in insertion order.
JSON.stringify(value, replacer, space): Converts a JavaScript value to a JSON string.value: The value to convert to a JSON string.replacer: (Optional) A function or an array that transforms the results.space: (Optional) A string or number of spaces to use for indentation.
JSON.parse(jsonString): Parses a JSON string, constructing the JavaScript value or object described by the string.jsonString: The JSON string to parse.
# Install dependencies
npm install
# Run a Inertz Script file
npm start examples/demo.is
npm run example
# Run arrays and objects example
node src/main.js examples/arrays-objects.is
# Run for loops example
node src/main.js examples/for-loops.is
# Run break and continue example
node src/main.js examples/break-continue.is
# Run array methods example
node src/main.js examples/array-methods.is
# Run advanced features example
node src/main.js examples/advanced-features.is
# Run specific file
node src/main.js path/to/your/file.is# Start the REPL
npm run repl
# In REPL, type Inertz Script code:
inertz> var numbers = [1, 2, 3, 4, 5];
inertz> var doubled = map(numbers, x => x * 2);
inertz> print(doubled);
[2, 4, 6, 8, 10]
inertz> async function test() { await delay(100); print("Delayed!"); }
inertz> test();
inertz> var myRegex = RegExp("hello", "i");
inertz> print(myRegex.test("Hello World")); // true
inertz> print(myRegex.exec("Hello World")); // ["Hello"]
inertz> var mySet = new Set([1, 2, 3]);
inertz> print(mySet.has(2)); // true
inertz> var myMap = new Map([["key", "value"]]);
inertz> print(myMap.get("key")); // "value"
inertz> var obj = {a: 1, b: "hello"};
inertz> print(JSON.stringify(obj)); // {"a":1,"b":"hello"}
inertz> exitnpm testtry {
// Risky code
throw "Something went wrong!";
} catch (error) {
print("Caught error:", error);
} finally {
print("This always executes");
}
function safeDivide(a, b) {
if (b == 0) {
throw "Division by zero";
}
return a / b;
}
try {
var result = safeDivide(10, 0);
} catch (error) {
print("Error:", error);
}
// Single parameter
var double = x => x * 2;
// Multiple parameters
var add = (a, b) => a + b;
// With array methods
var numbers = [1, 2, 3, 4, 5];
var doubled = map(numbers, x => x * 2);
var evens = filter(numbers, x => x % 2 == 0);
var sum = reduce(numbers, (acc, x) => acc + x, 0);
var people = [
{name: "Alice", age: 25, salary: 50000},
{name: "Bob", age: 30, salary: 60000}
];
// Chain operations with arrow functions
var highEarnerNames = map(
filter(people, person => person.salary >= 60000),
person => person.name
);
class Greeter {
constructor(name) {
this.name = name;
}
greet() {
print("Hello, " + this.name + "!");
}
}
var g = new Greeter("World");
g.greet(); // Output: Hello, World!
class Animal {
constructor(name) {
this.name = name;
}
speak() {
print(this.name + " makes a sound.");
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
super.speak(); // Call parent method
print(this.name + " barks!");
}
fetch() {
print(this.name + " fetches the ball.");
}
}
var myDog = new Dog("Buddy", "Golden Retriever");
myDog.speak();
myDog.fetch();
// Output:
// Buddy makes a sound.
// Buddy barks!
// Buddy fetches the ball.
// math.is
export var PI = 3.14159;
export function add(a, b) { return a + b; }
export default class Calculator {
add(a, b) { return a + b; }
}
// main.is
import { PI, add as sum } from "./math.is";
import MyCalc from "./math.is";
import * as MathUtils from "./math.is";
print(PI); // 3.14159
print(sum(1, 2)); // 3
var calc = new MyCalc();
print(calc.add(5, 6)); // 11
print(MathUtils.PI); // 3.14159
async function delayedPrint(message, ms) {
print("Starting delay for:", message);
await delay(ms);
print("Finished delay for:", message);
return "Done: " + message;
}
async function main() {
print("Main started.");
var result1 = await delayedPrint("First task", 50);
print(result1);
var result2 = await delayedPrint("Second task", 20);
print(result2);
print("Main finished.");
}
main();
// Expected (approximate) output order:
// Main started.
// Starting delay for: First task
// Finished delay for: First task
// Done: First task
// Starting delay for: Second task
// Finished delay for: Second task
// Done: Second task
// Main finished.
var asyncMultiply = async (a, b) => {
await delay(10);
return a * b;
};
async function calculate() {
var product = await asyncMultiply(3, 4);
print("Product:", product);
}
calculate(); // Output: Product: 12 (after a short delay)
class DataFetcher {
constructor(source) {
this.source = source;
}
async fetch() {
print("Fetching from " + this.source + "...");
await delay(100); // Simulate network request
return "Data from " + this.source;
}
}
async function app() {
var fetcher = new DataFetcher("API");
var data = await fetcher.fetch();
print(data);
}
app();
// Output:
// Fetching from API...
// Data from API
inertz-script/
├── src/
│ ├── main.js # Main CLI interface
│ ├── repl.js # Interactive REPL
│ ├── lexer.js # Tokenizer/Lexer
│ ├── parser.js # Parser (generates AST)
│ ├── ast.js # AST node definitions
│ ├── interpreter.js # Interpreter/Evaluator
│ ├── environment.js # Variable scoping
│ ├── builtins.js # Built-in functions
│ ├── token.js # Token definitions
│ └── test.js # Test suite
├── examples/
│ ├── demo.is # Language showcase
│ ├── fibonacci.is # Fibonacci sequence
│ ├── calculator.is # Simple calculator
│ ├── arrays-objects.is # Arrays and objects demo
│ ├── for-loops.is # For loops demonstration
│ ├── break-continue.is # Break and continue examples
│ ├── array-methods.is # Array methods demonstration
│ ├── advanced-features.is # Exception handling, arrow functions, etc.
│ ├── classes.is # Classes and inheritance examples
│ ├── modules/ # New: Directory for module examples
│ │ ├── main.is
│ │ └── math.is
│ └── async-await.is # New: Async/await examples
└── README.md
Inertz Script follows these design principles:
- Familiar Syntax: JavaScript-inspired syntax for ease of learning
- Strong Foundation: Proper lexer, parser, and AST-based interpreter
- Modular Architecture: Clean separation of concerns
- Extensible: Easy to add new features and built-ins
- Error Handling: Comprehensive error reporting with try/catch/finally
- Rich Data Types: Support for arrays and objects with intuitive syntax
- Flexible Iteration: Multiple loop types for different use cases
- Structured Control Flow: Break and continue for precise loop control
- Functional Programming: Array methods and arrow functions for elegant data transformation
- Exception Safety: Proper exception handling with custom error types
- Object-Oriented: Support for classes, inheritance,
this, andsuperfor structured code. - Asynchronous Programming: First-class support for
async/awaitfor handling non-blocking operations. - Regular Expressions: Built-in
RegExpconstructor and methods for powerful string pattern matching. - Standard Library: Expanded with
JSONobject andSet/Mapdata structures.
- Lexical Analysis: Converts source code into tokens (including
async,await, module keywords) - Parsing: Builds Abstract Syntax Tree (AST) using recursive descent parser (now includes
asyncfunctions,awaitexpressions,import,exportnodes) - Interpretation: Tree-walking interpreter with proper scoping, now fully asynchronous to handle Promises and
awaitexpressions. - Environment: Lexical scoping with environment chains
- Built-ins: Native function support with proper arity checking, including new
delayfor async examples,RegExpconstructor,Setconstructor,Mapconstructor, andJSONobject. - Data Structures: Native JavaScript arrays and objects with Inertz Script syntax, now including
InertzRegExp,InertzSet, andInertzMapwrappers. - Loop Constructs: Traditional for loops and for-in iteration
- Exception Handling: Try/catch/finally with custom exception types
- Arrow Functions: Concise function syntax with lexical scoping, now supporting
asyncvariants. - Enhanced Array Methods: Comprehensive functional programming support
- Object Methods: Better support for object-oriented patterns
- Classes and Inheritance: Custom
InertzClassandInertzInstanceruntime objects for full OOP support, includingasyncmethods. - Module System: Implemented
importandexportstatements with a module caching mechanism for code organization and reusability. - Regular Expressions: Introduced
InertzRegExpclass to wrap nativeRegExpobjects, exposingtest,exec,source, andflagsmethods.
- Try/Catch/Finally: Full exception handling support
- Custom Exceptions: Throw custom error messages
- Nested Exception Handling: Try/catch blocks can be nested
- Finally Blocks: Code that always executes regardless of exceptions
- Concise Syntax:
x => x * 2for single parameters,(a, b) => a + bfor multiple - Lexical Scoping: Arrow functions capture variables from enclosing scope
- Functional Programming: Perfect for use with array methods
- Expression Bodies: Arrow functions return the expression result automatically
- Async Arrow Functions:
async (a, b) => await somePromise()
- forEach: Execute function for each element without returning new array
- indexOf: Find the index of an element in the array
- includes: Check if array contains a specific element
- slice: Extract a portion of array without modifying original
- splice: Modify array by removing/adding elements at specific positions
- hasOwnProperty: Check if object has a specific property
- assign: Copy properties from source objects to target object
- Enhanced Object Manipulation: Better support for object-oriented patterns
- Class Declarations: Define custom types with
class MyClass { ... } - Constructors: Special
constructormethod for initializing new instances. - Methods: Functions defined within a class, automatically bound to
this. thisKeyword: Access instance properties and methods.- Inheritance: Extend existing classes using
extends. superKeyword: Call methods of the parent class.- Object Instantiation: Create new objects using the
newkeyword. - Async Methods:
asyncmethods within classes that can useawait.
importstatements: Support for named imports ({ name }), aliased named imports ({ name as alias }), namespace imports (* as namespace), default imports (defaultName), and side-effect imports ("module").exportstatements: Support for named exports (export var/function/class,export { name }), and default exports (export default ...).- Module Resolution: Basic relative path resolution for module imports.
- Module Caching: Modules are loaded and interpreted only once.
asynckeyword: Marks a function (or method, or arrow function) as asynchronous, allowing it to use theawaitkeyword and implicitly returning a Promise.awaitkeyword: Can only be used inside anasyncfunction. It pauses the execution of theasyncfunction until the Promise it's waiting on settles (resolves or rejects), and then resumes execution with the resolved value.- Promise Integration: The interpreter now natively handles JavaScript Promises, allowing them to be returned from
asyncfunctions and awaited.
RegExp(pattern, flags)constructor: Create regular expression objects.regex.test(string): Check for a match.regex.exec(string): Get match details.regex.source: Access the pattern string.regex.flags: Access the flags string.
// Example: Using RegExp
var emailRegex = RegExp("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
print(emailRegex.test("test@example.com")); // true
print(emailRegex.test("invalid-email")); // false
var globalMatch = RegExp("a", "g");
var text = "banana";
var match1 = globalMatch.exec(text); // ["a"]
var match2 = globalMatch.exec(text); // ["a"]
var match3 = globalMatch.exec(text); // ["a"]
var match4 = globalMatch.exec(text); // null
print(match1);
print(match2);
print(match3);
print(match4);
print(globalMatch.source); // "a"
print(globalMatch.flags); // "g"
new Set(iterable)constructor: Create Set objects.set.add(value): Add elements.set.delete(value): Remove elements.set.has(value): Check for element existence.set.clear(): Clear all elements.set.size: Get the number of elements.
// Example: Using Set
var mySet = new Set();
print(typeof(mySet)); // "set"
mySet.add(10);
mySet.add("hello");
mySet.add(10); // Duplicate, won't be added again
print(mySet.has(10)); // true
print(mySet.has("world")); // false
print(mySet.size); // 2
mySet.delete("hello");
print(mySet.has("hello")); // false
print(mySet.size); // 1
var initialSet = new Set([1, 2, 2, 3, "apple"]);
print(initialSet.size); // 4 (duplicates removed)
print(initialSet); // Set { 1, 2, 3, apple }
initialSet.clear();
print(initialSet.size); // 0
new Map(iterable)constructor: Create Map objects.map.set(key, value): Set key-value pairs.map.get(key): Retrieve values by key.map.delete(key): Remove key-value pairs.map.has(key): Check for key existence.map.clear(): Clear all entries.map.size: Get the number of entries.map.keys(): Get an array of keys.map.values(): Get an array of values.map.entries(): Get an array of[key, value]pairs.
// Example: Using Map
var myMap = new Map();
print(typeof(myMap)); // "map"
myMap.set("name", "Alice");
myMap.set("age", 30);
myMap.set(1, "one");
print(myMap.get("name")); // "Alice"
print(myMap.get(1)); // "one"
print(myMap.has("age")); // true
print(myMap.size); // 3
myMap.delete("age");
print(myMap.has("age")); // false
print(myMap.size); // 2
var initialMap = new Map([["fruit", "apple"], ["color", "red"]]);
print(initialMap.get("fruit")); // "apple"
print(initialMap.keys()); // ["fruit", "color"]
print(initialMap.values()); // ["apple", "red"]
print(initialMap.entries()); // [["fruit", "apple"], ["color", "red"]]
print(initialMap); // Map { fruit => apple, color => red }
initialMap.clear();
print(initialMap.size); // 0
JSON.stringify(value, replacer, space): Convert Inertz Script values to JSON strings.JSON.parse(jsonString): Parse JSON strings into Inertz Script values.
// Example: Using JSON
var data = {
name: "Inertz",
version: 1.0,
isInterpreter: true,
features: ["async", "modules", "classes"],
config: null
};
// Stringify with no formatting
var jsonString = JSON.stringify(data);
print(jsonString);
// Output: {"name":"Inertz","version":1,"isInterpreter":true,"features":["async","modules","classes"],"config":null}
// Stringify with 2-space indentation
var prettyJson = JSON.stringify(data, null, 2);
print(prettyJson);
// Output:
// {
// "name": "Inertz",
// "version": 1,
// "isInterpreter": true,
// "features": [
// "async",
// "modules",
// "classes"
// ],
// "config": null
// }
// Parse a JSON string
var parsedData = JSON.parse('{"user": "Alice", "id": 123, "active": true}');
print(parsedData.user); // "Alice"
print(parsedData.id); // 123
print(parsedData.active); // true
var jsonArray = JSON.parse('[10, "hello", false, null]');
print(jsonArray[0]); // 10
print(jsonArray[1]); // "hello"
print(jsonArray[2]); // false
print(jsonArray[3]); // null
- Bytecode compilation
- Debugging support