Skip to content
bizzehdee edited this page Jun 23, 2026 · 20 revisions

Language Reference

DScript is syntactically close to JavaScript (ES2020+). This page covers every supported language construct.

Variables

var x = 10;       // function-scoped, hoisted
let y = 20;       // block-scoped, not hoisted
const PI = 3.14;  // block-scoped, immutable binding

let and const obey block scoping — they are not visible outside the {} block they are declared in.

Types

Type Example literals
Number (integer) 0, 42, -7, 0xFF, 0b1010, 0o17
Number (float) 3.14, -0.5, 1e10
String "hello", 'world', `template`
Boolean true, false (stored as 1 / 0)
Null null
Undefined undefined
Object { key: value }
Array [1, 2, 3]
Function function f() {}, x => x

Operators

Category Operators
Arithmetic + - * / % ++ -- (prefix and postfix), unary + -
Assignment = += -= *= /= %= &= |= ^= <<= >>= >>>= &&= ||= ??=
Comparison < > <= >= == != === !==
Logical && || !
Bitwise & | ^ ~ << >> >>>
Nullish / optional ?? ?.
Other ?: ternary, typeof, instanceof, in, delete, new, ... spread

Template literals

var name = "Alice";
var msg  = `Hello, ${name}! You are ${20 + 5} years old.`;

Any expression may appear inside ${}. Nested template literals are allowed.

Objects

// Object literal
var obj = { x: 1, y: 2 };

// Shorthand property (name === value)
var name = "bob";
var record = { name, score: 100 };  // { name: "bob", score: 100 }

// Computed key
var key = "color";
var car = { [key]: "red" };   // { color: "red" }

// Property access
obj.x;       // dot notation
obj["y"];    // bracket notation

// Property deletion
delete obj.x;

Arrays

var arr = [10, 20, 30];
arr[0];            // 10
arr.length;        // 3
arr.push(40);      // append
arr.pop();         // remove last

Functions

// Named declaration (hoisted)
function add(a, b) { return a + b; }

// Anonymous expression
var mul = function(a, b) { return a * b; };

// Arrow — expression body (implicit return)
var sq  = x => x * x;
var sum = (a, b) => a + b;

// Arrow — block body
var clamp = (v, lo, hi) => {
    if (v < lo) return lo;
    if (v > hi) return hi;
    return v;
};

// Default parameters
function greet(name, msg = "Hello") {
    return `${msg}, ${name}!`;
}

// Rest parameters
function first(head, ...tail) { return head; }

// Spread in calls
function add3(a, b, c) { return a + b + c; }
add3(...[1, 2, 3]);  // 6

Closures

Every function captures its enclosing lexical scope:

function counter() {
    var n = 0;
    return () => ++n;
}
var inc = counter();
inc(); // 1
inc(); // 2
inc(); // 3

Classes and prototypes

function Animal(name) {
    this.name = name;
}
Animal.speak = function() {
    return `${this.name} makes a sound`;
};

function Dog(name) {
    Animal.call(this, name);
}
Dog.prototype = new Animal();

var d = new Dog("Rex");
d.speak();             // "Rex makes a sound"
d instanceof Dog;      // true
d instanceof Animal;   // true

class syntax is also accepted:

class Shape {
    constructor(color) {
        this.color = color;
    }
    describe() {
        return `A ${this.color} shape`;
    }
}

class Circle extends Shape {
    constructor(color, r) {
        super(color);
        this.radius = r;
    }
    area() {
        return Math.PI * this.radius * this.radius;
    }
}

Destructuring

// Array
var [a, b, c]      = [1, 2, 3];
var [x, , z]       = [10, 20, 30];      // skip middle
var [head, ...rest] = [1, 2, 3, 4];     // rest = [2,3,4]

// Object
var { x, y }            = { x: 1, y: 2 };
var { name: alias }     = { name: "alice" };  // rename
var { score = 0 }       = {};                  // default
var { a: { b } }        = { a: { b: 99 } };   // nested

Spread operator

// Array spread
var a = [1, 2];
var b = [...a, 3, 4];    // [1,2,3,4]

// Object spread
var base = { x: 1 };
var ext  = { ...base, y: 2 };  // { x:1, y:2 }

Nullish coalescing and optional chaining

var x = null;
var y = x ?? "default";    // "default"

var obj = { a: { b: 42 } };
obj?.a?.b;                  // 42
obj?.z?.w;                  // undefined (no throw)
obj?.fn?.(1, 2);            // undefined if fn absent

Logical assignment operators (ES2021)

Short-circuit compound assignments — the RHS is only evaluated when needed.

a &&= b   // assign b to a only if a is truthy  (a && (a = b))
a ||= b   // assign b to a only if a is falsy   (a || (a = b))
a ??= b   // assign b to a only if a is null or undefined

// All three also work on property and index targets:
obj.x &&= computeNewValue();
arr[i] ??= defaultValue;

Control flow

// if / else if / else
if (x > 0) { ... } else if (x < 0) { ... } else { ... }

// while
while (cond) { ... }

// do / while
do { ... } while (cond);

// for
for (var i = 0; i < 10; i++) { ... }

// for...in — property names
for (var key in obj) { console.log(key); }

// for...of — iterable values (arrays, generators, …)
for (var val of [1, 2, 3]) { console.log(val); }

// switch — no fallthrough; default may appear anywhere
switch (x) {
    case 1:  ...; break;
    default: ...;
    case 2:  ...;
}

// break / continue
while (true) {
    if (done) break;
    if (skip) continue;
}

continue inside a switch that is nested inside a loop targets the loop, not the switch.

Exception handling

try {
    throw new Error("something went wrong");
} catch (e) {
    console.log(e.message);
} finally {
    // always runs
}

// Throw any value
throw { code: 404, message: "not found" };

Generators

function* range(start, end) {
    for (var i = start; i < end; i++) yield i;
}

for (var n of range(0, 5)) console.log(n);  // 0 1 2 3 4

var gen = range(0, 3);
gen.next();  // { value: 0, done: false }
gen.next();  // { value: 1, done: false }
gen.next();  // { value: 2, done: false }
gen.next();  // { value: undefined, done: true }

Generators that contain no try/catch use a stackless state-machine path.

Async / await

async function fetchUser(id) {
    var data = await loadFromDb(id);
    return data.name;
}

fetchUser(1).then(name => console.log(name));

After engine.Run(program), call engine.DrainMicroTasks() from C# to flush the microtask queue and settle all pending promises.

Promises

var p = new Promise((resolve, reject) => {
    resolve(42);
});

p.then(v  => console.log("resolved:", v))
 .catch(e => console.log("rejected:", e));

// Static constructors
Promise.resolve(1);
Promise.reject("err");
Promise.all([p1, p2, p3]);
Promise.allSettled([p1, p2]);
Promise.race([p1, p2]);
Promise.any([p1, p2]);

Regular expressions

/pattern/flags         // literal
new RegExp("pattern", "flags")  // constructor

/hello/i.test("Hello World");   // true
/(\d+)/.exec("abc123");         // ["123", "123"]

var s = "hello world";
s.match(/\w+/g);       // ["hello", "world"]
s.replace(/o/g, "0");  // "hell0 w0rld"

Supported flags: g (global), i (ignoreCase), m (multiline).

typeof and instanceof

typeof 42;          // "number"
typeof "hi";        // "string"
typeof true;        // "boolean"
typeof undefined;   // "undefined"
typeof null;        // "object"
typeof {};          // "object"
typeof [];          // "object"
typeof function(){}; // "function"

[] instanceof Array;  // true

in and delete

var obj = { a: 1, b: 2 };
"a" in obj;    // true
delete obj.a;
"a" in obj;    // false

Clone this wiki locally