XE2 / DWS 2.2, Rosetta Code, Operators
Quite busy times with Delphi XE2 news appearing all over the web!
Quite busy times with Delphi XE2 news appearing all over the web!
Not exactly breaking news for those following the OP4JS news or the DWS SVN, but a new experimental set of classes is available for DWScript, which allows compiling DWScript source into JavaScript.
This allows to have Pascal code like this one for instance, be compiled into this html page (or see the outcome in jsfiddle), and be executable client-side by any modern browser (the demo uses HTML5’s Canvas). In the DWS source repository, you’ll find it in “MandelbrotJS” (requires Delphi Chromium Embedded to run).
The goal is to allow using a strongly typed, compile-time checked language in a Web-client environment. The code generation is also intended to be as lightweight as possible, without depending on a huge framework, and generate quite readable-looking JavaScript.
In the classic Delphi spirit, it’s all about allowing both a high-level usage, while still being open to low-level usage whenever you wish or need to.
The compiled Pascal functions can be used for DOM events or called from JS, or vice-versa, and you are f.i. able to use it only for the more complex routines or libraries for which straight JavaScript’s lack of strong typing and prototype-based objects would make it a developer-intensive and bug-prone approach.
This is still work in progress, only a (growing) subset of the DWS runtime library functions are supported at the moment, but most of the language is in working condition, including var parameters, classes, meta-classes, virtual methods & constructors, exceptions, bounds checking, contracts, etc. Currently, more than 85% of the DWS language & rtl unit tests pass (most of those not passing are related to Variants, destructors & ExceptObject).
The JS CodeGen can be invoked directly or via DWS filters, so you can have a single-source DWS code with portions running either server-side or browser-side.
FWIW, the DWS CodeGen classes were originally intended for compiling to SSE2-optimized floating point, either directly to x86-64 or via LLVM, but JavaScript is at the moment opening more opportunities, and modern JS engines are making decent use of SSE2 already. Last but not least, in the near term, it’s probably best to let the dust of the upcoming Delphi XE2 settle a bit 😉
SVN version of DWScript adds a long-missing functionality in DWS: dynamic arrays. They provide a language-based alternative to the list and collections classes that had to be used so far.
They extend the “new” keyword for instantiation, and introduce pseudo-method semantics in addition to the traditional semantics for Low(), High() and Length().
var a : array of Integer; var i : Integer; a := new Integer[10]; for i := a.Low to a.High do a[i] := i;
The pseudo-methods currently available on dynamic arrays are:
Dynamic arrays in DWS are pure reference types and they behave a bit like a TList<T> would in Delphi, as SetLength() is a method, which modifies the array, rather than a global procedure, which can create a new copy of the array (as in Delphi), ie. in DWScript, if you have:
var a, b : array of Integer; a := new Integer[5]; b := a; a[1] := 1; PrintLn( b[1] ); a.SetLength(10); a[1] := 2; PrintLn( b[1] );
It will print 1 and 2. A Delphi version using “SetLength(a, 10)” instead would print 1 and 1.
In other words, in DWScript, if you want a new dynamic array instance, you use “new”, if want to make a copy of a dynamic array, you have to use .Copy(), if you want to resize, you use .SetLength(). Whereas in classic Delphi, all three aspects are behavioral variants of the SetLength() global procedure.
Note that if the dynamic arrays in DWS currently rely on compiler magic, there is a long term goal of having them mappable to a “regular” generic container class.
DWScript SVN version just introduced support for the “new” keyword and “default” constructors.
The syntax is similar to that of Oxygene/Prism, you can now create a new instance with
obj1 := new TSomeObject; obj2 := new TSomeOtherObject(param1, param2);
By default, the above syntax will be duck-typed to the .Create constructor of a given class, but you can alternatively specify a “default” constructor (one per class) to select a specific named constructor that “new” will use:
type TSomeClass = class constructor ImTheOne; default; end;
The Oxygene syntax is also extended in two ways, you can use “new” on a metaclass variable:
type TSomeObjectClass = class of TSomeObject; ... var ref : TSomeObjectClass; ... obj := new ref;
And you can further use it on an expression that returns a metaclass by placing it between brackets:
function TOtherClass.GetMetaClass : TSomeObjectClass; ... var o : TOtherClass; ... obj := new (o.GetMetaClass)(param1, param2);
The brackets are not just there to make it look like Turbo Pascal-era code, they are required for disambiguation, f.i. the two lines
obj1 := new TSomeClass(param); obj2 := new (TSomeClass(param));
are compiled as a syntax variation of
obj1 := TSomeClass.Create(param); obj2 := TSomeClass(param).Create;
The “new” keyword is also planned to be used as the basis of dynamic array instantiation.
I’m looking for a good name for a “TObject ancestor” class, that would introduce no Pascal baggage: no “Create”, no “Destroy”, no “Free”, etc.
TObject would become a subclass of that root class.
Executive summary of recent DWS changes from the bleeding edge:
Something “big” is also brewing in the DWScript lab, if not quite ready for prime-time just yet 😉
Here is a small poll to help me decide in which direction to go about dynamic arrays in DWScript. The poll is at the bottom of the post, to encourage reading before voting 😉
…or why you can’t hide under the complexity carpet 😉
As uncovered in previous episodes, one of the keys behind TMonitor performance issues is that it allocates a dynamic block of memory for its locking purposes, and when those blocks end up allocated on the same CPU cache line, the two TMonitor on the same cache line will end up fighting for the cache line, resulting in a drastic drop of performance and thread contention. The technical term for that behavior is false sharing.
(more…)
Last episode in the TMonitor saga. In the previous episode, Chris Rolliston posted a more complete test case, for which he got surprising results (including that a Critical Section approach wouldn’t scale with the thread count). Starting from his code I initially also got similar surprising results.
edit: apparently the “crash” part of the TMonitor issues have been acknowledged by the powers that be, and a hotfix could be on the way, though it points back to QC 78415, an issue reported in 2009, ouch. Guess those 4 bytes per instance haven’t seen much use…
(more…)
Primoz Gabrijelcic recently reported a possible bug with TMonitor, in the more advanced side of TMonitor.
However, when experimenting with it for DWS, I bumped on issues in the basic usage scenarios too, and reverted to using critical sections. It seems that as of Delphi XE, short of a patch, TMonitor is just a waste of 4 bytes per object instance.
(more…)