-
-
Notifications
You must be signed in to change notification settings - Fork 5
Engine
ScriptEngine is the central object. It holds the global variable environment, the native function registry, and all runtime state.
using DScript;
using DScript.Extras;
var engine = new ScriptEngine();
// Register the DScript.Extras standard library (optional but recommended)
new EngineFunctionLoader().RegisterFunctions(engine);To restrict system access, pass an EnginePermissions value — see Permissions.
new EngineFunctionLoader().RegisterFunctions(engine, EnginePermissions.FileSystem);engine.Execute("var x = 6 * 7;");Execute compiles and runs the code in one step. ScriptException and JITException are caught internally and written to Console.Error; all other exceptions propagate. Use Run when you want exceptions to propagate.
try
{
engine.Run(ScriptEngine.Compile("var x = undeclaredFn();"));
}
catch (JITException ex)
{
Console.Error.WriteLine(ex.ToString()); // includes script stack trace
}ScriptEngine.Compile is a static method — the resulting Chunk is engine-independent and can be shared or cached.
var program = ScriptEngine.Compile("var answer = 6 * 7;");
engine.Run(program); // fast — no re-parsingEvaluate a single expression and return its value as a ScriptVarLink.
var link = engine.EvalComplex("2 + 2");
Console.WriteLine(link.Var.Int); // 4Controls whether the bytecode optimiser runs when the engine compiles source
(constant folding, dead-code elimination, super-instruction fusion, narrow
encoding). It is true by default and is honoured by Execute, EvalComplex,
and module compilation. Set it to false to compile straight, unoptimised
bytecode — handy for inspecting or debugging codegen. Results are identical
either way; only the emitted bytecode differs.
var engine = new ScriptEngine { EnableOptimizer = false };
engine.Execute("var x = 2 + 3 * 4;"); // compiled without constant foldingBounds nested script-function recursion (default 10000). Exceeding it throws a
catchable "Maximum call stack size exceeded" error instead of letting the native
.NET stack overflow (which would crash the process). Tail calls are trampolined
and don't count toward the depth. See Resource Limits for
details.
var engine = new ScriptEngine { MaxCallStackDepth = 5000 };After execution, global variables are accessible via engine.Root:
engine.Execute("var name = 'Alice'; var age = 30;");
string name = engine.Root.GetParameter("name").String; // "Alice"
int age = engine.Root.GetParameter("age").Int; // 30GetParameter returns a ScriptVar. Use .Int, .String, .Double, .Bool, or .IsUndefined / .IsNull to read its value.
engine.Execute("function square(n) { return n * n; }");
var fn = engine.Root.GetParameter("square");
var result = engine.CallFunction(fn, null, new ScriptVar(9));
Console.WriteLine(result.Int); // 81CallFunction(fn, thisArg, params...) accepts any number of ScriptVar arguments. Pass null for thisArg to use the global scope.
engine.AddNative("function add(a, b)", (scope, userData) =>
{
int a = scope.GetParameter("a").Int;
int b = scope.GetParameter("b").Int;
scope.ReturnVar.Int = a + b;
}, null);
engine.Execute("console.log(add(3, 4));"); // 7The first argument is a function signature string — the parameter names declared here are how values are retrieved inside the callback. userData is the third argument passed to AddNative and is forwarded to every invocation.
Save all script-side variables to a byte array and restore them later on a fresh engine (natives must be re-registered first):
engine.Execute("var counter = 42;");
byte[] snapshot = engine.SerializeState();
var engine2 = new ScriptEngine();
new EngineFunctionLoader().RegisterFunctions(engine2);
engine2.DeserializeState(snapshot);
Console.WriteLine(engine2.Root.GetParameter("counter").Int); // 42Supply a callback to resolve require() and import paths:
engine.ModuleLoader = (path, fromPath) =>
File.ReadAllText(Path.Combine(baseDir, path + ".ds"));See Modules for the full module system.
ScriptVar represents any DScript value — number, string, boolean, object, array, function, null, or undefined.
| Member | Description |
|---|---|
new ScriptVar(int) |
Create an integer value |
new ScriptVar(double) |
Create a floating-point value |
new ScriptVar(string) |
Create a string value |
new ScriptVar(bool) |
Create a boolean value |
new ScriptVar(ScriptVar.Flags.Null) |
Create a null value |
new ScriptVar(ScriptVar.Flags.Undefined) |
Create undefined |
.Int |
Read/write as integer |
.Double |
Read/write as double |
.String |
Read/write as string |
.Bool |
Read as boolean (non-zero / non-empty) |
.IsNull |
True if the value is null |
.IsUndefined |
True if the value is undefined |
.IsArray |
True if the value is an array |
.IsFunction |
True if the value is a function |
.GetArrayLength() |
Number of array elements |
.GetArrayIndex(i) |
Get element at index i
|
.SetArrayIndex(i, val) |
Set element at index i
|
.FindChild(name) |
Find a named property (returns ScriptVarLink?) |
.AddChild(name, val) |
Add a named property |
.GetParsableString() |
Stringify the value (for display) |
.SetData(obj) / .GetData()
|
Attach/retrieve a native CLR object |
| Type | When thrown |
|---|---|
JITException |
Runtime error in script code (carries .ScriptStackTrace) |
ScriptException |
Explicit throw in script, or native code calling throw new ScriptException(msg)
|
ScriptTimeoutException |
Wall-clock or instruction limit exceeded — cannot be caught by script try/catch
|
PermissionException |
Script attempted an operation denied by EnginePermissions
|