arsd.script
FIXME:
easier object interop with D
FIXME:
prettier stack trace when sent to D
FIXME:
the debugger statement from javascript might be cool to throw in too.
FIXME:
add continuations or something too
FIXME:
Also ability to get source code for function something so you can mixin.
Script features:
FIXME:
add COM support on Windows
OVERVIEW
easy interop with D thanks to arsd.jsvar. When interpreting, pass a var object to use as globals.
This object also contains the global state when interpretation is done.
mostly familiar syntax, hybrid of D and Javascript
simple implementation is moderately small and fairly easy to hack on (though it gets messier by the day), but it isn't made for speed.
SPECIFICS
string literals come in "foo" or 'foo', like Javascript, or `raw string` like D. Also come as “nested “double quotes” are an option!”
mixin aka eval (does it at runtime, so more like eval than mixin, but I want it to look like D)
scope guards, like in D
try/catch/finally/throw
You can use try as an expression without any following catch to return the exception:
var a = try throw "exception";; // the double ; is because one closes the try, the second closes the var
// a is now the thrown exception
for/while/foreach
D style operators: +-/* on all numeric types, ~ on strings and arrays, |&^ on integers.
Operators can coerce types as needed: 10 ~ "hey" == "10hey". 10 + "3" == 13.
Any math, except bitwise math, with a floating point component returns a floating point component, but pure int math is done as ints (unlike Javascript btw).
Any bitwise math coerces to int.
So you can do some type coercion like this:
a = a|0; // forces to int
a = "" ~ a; // forces to string
a = a+0.0; // coerces to float
Though casting is probably better.
Type coercion via cast, similarly to D.
var a = "12";
a.typeof == "String";
a = cast(int) a;
a.typeof == "Integral";
a == 12;
Supported types for casting to: int/long (both actually an alias for long, because of how var works), float/double/real, string, char/dchar (these return *integral* types), and arrays, int[], string[], and float[].
This forwards directly to the D function var.opCast.
some operator overloading on objects, passing opBinary(op, rhs), length, and perhaps others through like they would be in D.
opIndex(name)
opIndexAssign(value, name) // same order as D, might some day support [n1, n2] => (value, n1, n2)
obj._prop("name", value); // bypasses operator overloading, useful for use inside the opIndexAssign especially
Note:
if opIndex is not overloaded, getting a non-existent member will actually add it to the member. This might be a bug but is needed right now in the D impl for nice chaining. Or is it? FIXME
if/else
array slicing, but note that slices are rvalues currently
variables must start with A-Z, a-z, , or $, then must be [A-Za-z0-9]*.
(The $ can also stand alone, and this is a special thing when slicing, so you probably shouldn't use it at all.).
Variable names that start with _ are reserved and you shouldn't use them.
int, float, string, array, bool, and json!q{} literals
var.prototype, var.typeof. prototype works more like Mozilla's _proto__ than standard javascript prototype.
classes:
// inheritance works
class Foo : bar {
// constructors, D style
this(var a) { ctor.... }
// static vars go on the auto created prototype
static var b = 10;
// instance vars go on this instance itself
var instancevar = 20;
// "virtual" functions can be overridden kinda like you expect in D, though there is no override keyword
function virt() {
b = 30; // lexical scoping is supported for static variables and functions
// but be sure to use this. as a prefix for any class defined instance variables in here
this.instancevar = 10;
}
}
var foo = new Foo(12);
foo.newFunc = function() { this.derived = 0; }; // this is ok too, and scoping, including 'this', works like in Javascript
You can also use 'new' on another object to get a copy of it.
return, break, continue, but currently cannot do labeled breaks and continues
__FILE__, __LINE__, but currently not as default arguments for D behavior (they always evaluate at the definition point)
most everything are expressions, though note this is pretty buggy! But as a consequence:
for(var a = 0, b = 0; a < 10; a+=1, b+=1) {}
won't work but this will:
for(var a = 0, b = 0; a < 10; {a+=1; b+=1}) {}
You can encase things in {} anywhere instead of a comma operator, and it works kinda similarly.
{} creates a new scope inside it and returns the last value evaluated.
functions:
var fn = function(args...) expr;
or
function fn(args....) expr;
Special function local variables:
arguments = var[] of the arguments passed
thisfunc = reference to the function itself
this = reference to the object on which it is being called - note this is like Javascript, not D.
args can say var if you want, but don't have to
default arguments supported in any position
when calling, you can use the default keyword to use the default value in any position
FIXME:
make sure superclass ctors are called
Might be nice:
varargs
lambdas
- class ScriptCompileException: object.Exception;
- script to follow
Page generated by Ddoc.