The language
SandScript looks like JavaScript with constraints. This chapter shows the surface, then records what is absent and where behavior deviates.
Variables and expressions
// Variables (let, const, var all supported)
let name = "Claude";
const count = 42; // cannot be reassigned
var active = true; // alias for let (no hoisting)
// Comma-separated declarations
let a = 1, b = 2, c = 3;
// Operators work normally
let sum = 1 + 2;
let isEqual = a === b;
// Arrays and objects
let numbers = [1, 2, 3];
let person = { name: "Alice", age: 30 };
let first = numbers[0];
let personName = person.name;
Functions
Function expressions are arrow functions. Function declarations and the ES5 constructor-function pattern also work.
let square = (x) => x * x;
let max = (a, b) => {
if (a > b) {
return a;
} else {
return b;
}
};
// Higher-order functions
let doubled = numbers.map((x) => x * 2);
let total = numbers.reduce((acc, x) => acc + x, 0);
Control flow and loops
for (let i = 0; i < 10; i++) {
Console.log(i);
}
try {
throw { type: "Error", message: "Something went wrong" };
} catch (e) {
Console.log(e.message);
}
new, this, and the ternary
? : operator work normally. async and
await, destructuring, for...of,
switch, and spread are fully supported.
Exports
export works for named declarations at the top level.
Export is metadata for cross-session invocation. It signals intent
and does not gate access.
export const add = (x, y) => x + y;
export function multiply(x, y) { return x * y; }
Classes
SandScript supports class declarations, class expressions, and
export class.
class Animal {
legs = 4; // instance field
static kingdom = "Animalia"; // static field
constructor(name) { this.name = name; }
describe() { return this.name; } // prototype method
get title() { return "Mr. " + this.name; }
set title(v) { this.name = v; }
static tag(a) { return "tag:" + a.name; }
}
class Bird extends Animal {
legs = 2; // runs after super() returns
constructor(name) { super(name); }
describe() { return "bird " + super.describe(); }
}
These all work: extends, super(...),
super.method(...), super.x reads and
writes, new.target, instanceof, static
inheritance, accessors, computed keys, async and generator methods,
static initialization blocks, this in static field
initializers, and private members (#name fields,
methods, accessors, and statics).
The parent of extends is a SandScript class or
function, one of the built-in constructors whose instances are
plain objects — Error, TypeError,
ReferenceError, RangeError,
SyntaxError, and Object — or an external
handle the host registered as constructible. Every other built-in
(Map, Set, Array, typed
arrays, RegExp, Promise) throws a
catchable TypeError when the class evaluates, because their
instances are dedicated heap shapes, not plain objects.
A derived error class gets the full chain: instanceof
answers through the family, super(message) sets the
own message string, and the inherited
name identifies the family until the class shadows
it.
Not supported
| Feature | Status |
|---|---|
export default | Parse error |
export { a, b } | Parse error. Use export const per declaration. |
var is supported but behaves like let:
no hoisting and no function scoping.
Recorded deviations from JavaScript
Each deviation is observable only through reflection or an exotic corner:
- Class methods are enumerable own properties of the prototype object. Instance enumeration matches JavaScript.
- A derived constructor binds
thisbeforesuper()runs. SandScript accepts a read ofthisbeforesuper(); JavaScript reports a runtime error. - A return-object override inside a parent constructor called through
super()does not replacethis. super[expr],delete super.x, and increment onsuper.xare parse errors. Plain reads, writes, compound assignment, andsuper.method(...)all work.- Class methods are constructible, as object-literal methods already are.
- Private members store under hidden keys invisible to enumeration, spread, and
JSON.stringify. Private-name identity is per class definition, not per class evaluation. - Classes and built-in constructors expose
nameas an enumerable own property. An anonymous class expression has noname; JavaScript infers one from the binding. - Computed static member keys evaluate after every instance member key, not interleaved in source order.
super()against a built-in parent evaluates toundefined.new Error()and a derivedsuper()both set an ownmessage; JavaScript leaves the own property off. The{ cause }options argument is unsupported.